1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LibTomCrypt is a library that provides various cryptographic
4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * algorithms in a highly modular and flexible manner.
5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library is free for all purposes without any express
7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * guarantee it works.
8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "tomcrypt.h"
12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @file rsa_verify_hash.c
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  RSA PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef MRSA
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  PKCS #1 de-sign then v1.5 or PSS depad
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param sig              The signature data
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param siglen           The length of the signature data (octets)
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param hash             The hash of the message that was signed
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param hashlen          The length of the hash of the message that was signed (octets)
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param padding          Type of padding (LTC_PKCS_1_PSS or LTC_PKCS_1_V1_5)
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param hash_idx         The index of the desired hash
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param saltlen          The length of the salt used during signature
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param stat             [out] The result of the signature comparison, 1==valid, 0==invalid
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param key              The public RSA key corresponding to the key that performed the signature
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK on success (even if the signature is invalid)
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rsa_verify_hash_ex(const unsigned char *sig,      unsigned long siglen,
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                       const unsigned char *hash,     unsigned long hashlen,
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                             int            padding,
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                             int            hash_idx, unsigned long saltlen,
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                             int           *stat,     rsa_key      *key)
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  unsigned long modulus_bitlen, modulus_bytelen, x;
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  int           err;
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  unsigned char *tmpbuf;
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  LTC_ARGCHK(hash  != NULL);
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  LTC_ARGCHK(sig   != NULL);
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  LTC_ARGCHK(stat  != NULL);
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  LTC_ARGCHK(key   != NULL);
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* default to invalid */
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  *stat = 0;
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* valid padding? */
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  if ((padding != LTC_PKCS_1_V1_5) &&
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      (padding != LTC_PKCS_1_PSS)) {
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_PK_INVALID_PADDING;
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  if (padding == LTC_PKCS_1_PSS) {
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* valid hash ? */
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       return err;
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* get modulus len in bits */
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  modulus_bitlen = mp_count_bits( (key->N));
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* outlen must be at least the size of the modulus */
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  modulus_bytelen = mp_unsigned_bin_size( (key->N));
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  if (modulus_bytelen != siglen) {
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     return CRYPT_INVALID_PACKET;
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* allocate temp buffer for decoded sig */
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  tmpbuf = XMALLOC(siglen);
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  if (tmpbuf == NULL) {
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     return CRYPT_MEM;
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* RSA decode it  */
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  x = siglen;
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) {
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     XFREE(tmpbuf);
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     return err;
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* make sure the output is the right size */
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  if (x != siglen) {
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     XFREE(tmpbuf);
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     return CRYPT_INVALID_PACKET;
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  if (padding == LTC_PKCS_1_PSS) {
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* PSS decode and verify it */
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat);
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  } else {
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* PKCS #1 v1.5 decode it */
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    unsigned char *out;
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    unsigned long outlen, loid[16];
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int           decoded;
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ltc_asn1_list digestinfo[2], siginfo[2];
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* not all hashes have OIDs... so sad */
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (hash_descriptor[hash_idx].OIDlen == 0) {
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       err = CRYPT_INVALID_ARG;
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       goto bail_2;
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* allocate temp buffer for decoded hash */
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3;
111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    out    = XMALLOC(outlen);
112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (out == NULL) {
113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      err = CRYPT_MEM;
114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      goto bail_2;
115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) {
118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      XFREE(out);
119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      goto bail_2;
120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */
123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* construct the SEQUENCE
124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      SEQUENCE {
125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         SEQUENCE {hashoid OID
126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                   blah    NULL
127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         }
128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         hash    OCTET STRING
129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   */
131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0]));
132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL,              NULL,                          0);
133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_SET_ASN1(siginfo,    0, LTC_ASN1_SEQUENCE,          digestinfo,                    2);
134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_SET_ASN1(siginfo,    1, LTC_ASN1_OCTET_STRING,      tmpbuf,                        siglen);
135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       XFREE(out);
138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       goto bail_2;
139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* test OID */
142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if ((digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) &&
143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        (XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx].OID, sizeof(unsigned long) * hash_descriptor[hash_idx].OIDlen) == 0) &&
144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        (siginfo[1].size == hashlen) &&
145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        (XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) {
146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       *stat = 1;
147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    zeromem(out, outlen);
151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    XFREE(out);
153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectbail_2:
156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  zeromem(tmpbuf, siglen);
158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  XFREE(tmpbuf);
160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  return err;
161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif /* MRSA */
164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/pk/rsa/rsa_verify_hash.c,v $ */
166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.11 $ */
167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/12/04 03:09:28 $ */
168