File Coverage

inc/matrixssl-3-9-3-open/crypto/pubkey/rsa.c
Criterion Covered Total %
statement 191 296 64.5
branch 88 192 45.8
condition n/a
subroutine n/a
pod n/a
total 279 488 57.1


line stmt bran cond sub pod time code
1             /**
2             * @file rsa.c
3             * @version 950bba4 (HEAD -> master)
4             *
5             * RSA crypto.
6             */
7             /*
8             * Copyright (c) 2013-2017 INSIDE Secure Corporation
9             * Copyright (c) PeerSec Networks, 2002-2011
10             * All Rights Reserved
11             *
12             * The latest version of this code is available at http://www.matrixssl.org
13             *
14             * This software is open source; you can redistribute it and/or modify
15             * it under the terms of the GNU General Public License as published by
16             * the Free Software Foundation; either version 2 of the License, or
17             * (at your option) any later version.
18             *
19             * This General Public License does NOT permit incorporating this software
20             * into proprietary programs. If you are unable to comply with the GPL, a
21             * commercial license for this software may be purchased from INSIDE at
22             * http://www.insidesecure.com/
23             *
24             * This program is distributed in WITHOUT ANY WARRANTY; without even the
25             * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26             * See the GNU General Public License for more details.
27             *
28             * You should have received a copy of the GNU General Public License
29             * along with this program; if not, write to the Free Software
30             * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31             * http://www.gnu.org/copyleft/gpl.html
32             */
33             /******************************************************************************/
34              
35             #include "../cryptoImpl.h"
36              
37             /******************************************************************************/
38             /* TODO - the following functions are not implementation layer specific...
39             move to a common file?
40              
41             Matrix-specific starts at #ifdef USE_MATRIX_RSA
42             */
43              
44             #define ASN_OVERHEAD_LEN_RSA_SHA2 19
45             #define ASN_OVERHEAD_LEN_RSA_SHA1 15
46              
47             #ifdef USE_MATRIX_RSA
48 1057           int32_t pubRsaDecryptSignedElement(psPool_t *pool, psRsaKey_t *key,
49             unsigned char *in, psSize_t inlen,
50             unsigned char *out, psSize_t outlen,
51             void *data)
52             {
53             int32_t signatureAlgorithm, rc;
54              
55 1057           rc = psHashLenToSigAlg(outlen, PS_RSA);
56 1057 50         if (rc < 0)
57             {
58 0           return rc;
59             }
60              
61 1057           signatureAlgorithm = rc;
62              
63 1057           return pubRsaDecryptSignedElementExt(pool, key, in, inlen,
64             out, outlen,
65             signatureAlgorithm, data);
66             }
67              
68 1057           int32_t pubRsaDecryptSignedElementExt(psPool_t *pool, psRsaKey_t *key,
69             unsigned char *in, psSize_t inlen,
70             unsigned char *out, psSize_t outlen,
71             int32_t signatureAlgorithm, void *data)
72             {
73             unsigned char *c, *front, *end;
74             uint16_t outlenWithAsn, len, plen;
75             int32_t oi, rc;
76              
77             /* The issue here is that the standard RSA decryption routine requires
78             the user to know the output length (usually just a hash size). With
79             these "digitally signed elements" there is an algorithm
80             identifier surrounding the hash so we use the known magic numbers as
81             additional lengths of the wrapper since it is a defined ASN sequence,
82             ASN algorithm oid, and ASN octet string */
83 1057 50         if (outlen == SHA256_HASH_SIZE)
84             {
85 1057           outlenWithAsn = SHA256_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2;
86             }
87 0 0         else if (outlen == SHA1_HASH_SIZE)
88             {
89 0           outlenWithAsn = SHA1_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA1;
90             }
91 0 0         else if (outlen == SHA384_HASH_SIZE)
92             {
93 0           outlenWithAsn = SHA384_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2;
94             }
95 0 0         else if (outlen == SHA512_HASH_SIZE)
96             {
97 0           outlenWithAsn = SHA512_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2;
98             }
99             else
100             {
101             psTraceIntCrypto("Unsupported decryptSignedElement hash %d\n", outlen);
102 0           return PS_FAILURE;
103             }
104              
105 1057           front = c = psMalloc(pool, outlenWithAsn);
106 1057 50         if (front == NULL)
107             {
108 0           return PS_MEM_FAIL;
109             }
110              
111 1057 50         if ((rc = psRsaDecryptPub(pool, key, in, inlen, c, outlenWithAsn, data)) < 0)
112             {
113 0           psFree(front, pool);
114             psTraceCrypto("Couldn't public decrypt signed element\n");
115 0           return rc;
116             }
117              
118             /* Parse it */
119 1057           end = c + outlenWithAsn;
120              
121             /* @note Below we do a typecast to const to avoid a compiler warning,
122             although it should be fine to pass a non const pointer into an
123             api declaring it const, since it is just the API declaring the
124             contents will not be modified within the API. */
125 1057 50         if (getAsnSequence((const unsigned char **) &c,
126 1057           (uint16_t) (end - c), &len) < 0)
127             {
128             psTraceCrypto("Couldn't parse signed element sequence\n");
129 0           psFree(front, pool);
130 0           return PS_FAILURE;
131             }
132 1057 50         if (getAsnAlgorithmIdentifier((const unsigned char **) &c,
133 1057           (uint16_t) (end - c), &oi, &plen) < 0)
134             {
135             psTraceCrypto("Couldn't parse signed element octet string\n");
136 0           psFree(front, pool);
137 0           return PS_FAILURE;
138             }
139              
140 1057 50         if (oi == OID_SHA256_ALG)
141             {
142 1057 50         psAssert(outlen == SHA256_HASH_SIZE);
143             }
144 0 0         else if (oi == OID_SHA1_ALG)
145             {
146 0 0         psAssert(outlen == SHA1_HASH_SIZE);
147             }
148 0 0         else if (oi == OID_SHA384_ALG)
149             {
150 0 0         psAssert(outlen == SHA384_HASH_SIZE);
151             }
152             # ifdef USE_MD2
153             else if (oi == OID_MD2_ALG)
154             {
155             psAssert(outlen == MD5_HASH_SIZE);
156             }
157             # endif /* USE_MD2 */
158             # ifdef USE_MD5
159 0 0         else if (oi == OID_MD5_ALG)
160             {
161 0 0         psAssert(outlen == MD5_HASH_SIZE);
162             }
163             # endif /* USE_MD5 */
164             else
165             {
166 0 0         psAssert(outlen == SHA512_HASH_SIZE);
167             }
168              
169             /* Note the last test here requires the buffer to be exactly outlen bytes */
170 2114 50         if ((end - c) < 1 || (*c++ != ASN_OCTET_STRING) ||
171 2114 50         getAsnLength((const unsigned char **) &c, (uint16_t) (end - c), &len) < 0 ||
172 1057           (uint32_t) (end - c) != outlen)
173             {
174              
175             psTraceCrypto("Couldn't parse signed element octet string\n");
176 0           psFree(front, pool);
177 0           return PS_FAILURE;
178             }
179             /* Will finally be sitting at the hash now */
180 1057           memcpy(out, c, outlen);
181 1057           psFree(front, pool);
182 1057           return PS_SUCCESS;
183             }
184              
185             /*
186             ASN wrappers around standard hash signatures. These versions sign
187             a BER wrapped hash. Here are the well-defined wrappers:
188             */
189             static const unsigned char asn256dsWrap[] = { 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60,
190             0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,0x01, 0x05, 0x00, 0x04, 0x20 };
191             # ifdef USE_SHA384
192             static const unsigned char asn384dsWrap[] = { 0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60,
193             0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,0x02, 0x05, 0x00, 0x04, 0x30 };
194             # endif
195             static const unsigned char asn1dsWrap[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,
196             0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 };
197              
198 1146           int32_t privRsaEncryptSignedElement(psPool_t *pool, psRsaKey_t *key,
199             const unsigned char *in, psSize_t inlen,
200             unsigned char *out, psSize_t outlen,
201             void *data)
202             {
203             unsigned char c[MAX_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2];
204             uint32_t inlenWithAsn;
205              
206 1146           switch (inlen)
207             {
208             # ifdef USE_SHA256
209             case SHA256_HASH_SIZE:
210 1146           inlenWithAsn = inlen + ASN_OVERHEAD_LEN_RSA_SHA2;
211 1146           memcpy(c, asn256dsWrap, ASN_OVERHEAD_LEN_RSA_SHA2);
212 1146           memcpy(c + ASN_OVERHEAD_LEN_RSA_SHA2, in, inlen);
213 1146           break;
214             # endif
215             # ifdef USE_SHA1
216             case SHA1_HASH_SIZE:
217 0           inlenWithAsn = inlen + ASN_OVERHEAD_LEN_RSA_SHA1;
218 0           memcpy(c, asn1dsWrap, ASN_OVERHEAD_LEN_RSA_SHA1);
219 0           memcpy(c + ASN_OVERHEAD_LEN_RSA_SHA1, in, inlen);
220 0           break;
221             # endif
222             # ifdef USE_SHA384
223             case SHA384_HASH_SIZE:
224 0           inlenWithAsn = inlen + ASN_OVERHEAD_LEN_RSA_SHA2;
225 0           memcpy(c, asn384dsWrap, ASN_OVERHEAD_LEN_RSA_SHA2);
226 0           memcpy(c + ASN_OVERHEAD_LEN_RSA_SHA2, in, inlen);
227 0           break;
228             # endif
229             default:
230 0           return PS_UNSUPPORTED_FAIL;
231             }
232 1146 50         if (psRsaEncryptPriv(pool, key, c, inlenWithAsn,
233             out, outlen, data) < 0)
234             {
235             psTraceCrypto("privRsaEncryptSignedElement failed\n");
236 0           memzero_s(c, sizeof(c));
237 0           return PS_PLATFORM_FAIL;
238             }
239 1146           memzero_s(c, sizeof(c));
240 1146           return PS_SUCCESS;
241             }
242              
243             /******************************************************************************/
244             /**
245             Initialize an allocated RSA key.
246              
247             @note that in this case, a psRsaKey_t is a structure type.
248             This means that the caller must have statically or dynamically allocated
249             the structure before calling this Api.
250              
251             TODO, may not be necessary, since crypt apis also take pool.
252             @param[in] pool The pool to use to allocate any temporary working memory
253             beyond what is provided in the 'key' structure.
254              
255             @param[in,out] key A pointer to an allocated (statically or dynamically)
256             key structure to be initalized as a blank RSA keypair.
257             */
258 3541           int32_t psRsaInitKey(psPool_t *pool, psRsaKey_t *key)
259             {
260 3541 50         if (!key)
261             {
262 0           return PS_MEM_FAIL;
263             }
264 3541           memset(key, 0x0, sizeof(psRsaKey_t));
265 3541           key->pool = pool;
266 3541           return PS_SUCCESS;
267             }
268              
269             /*
270             Zero an RSA key. The caller is responsible for freeing 'key' if it is
271             allocated (or not if it is static, or stack based).
272             */
273 3290           void psRsaClearKey(psRsaKey_t *key)
274             {
275 3290           pstm_clear(&(key->N));
276 3290           pstm_clear(&(key->e));
277 3290           pstm_clear(&(key->d));
278 3290           pstm_clear(&(key->p));
279 3290           pstm_clear(&(key->q));
280 3290           pstm_clear(&(key->dP));
281 3290           pstm_clear(&(key->dQ));
282 3290           pstm_clear(&(key->qP));
283 3290           key->size = 0;
284 3290           key->optimized = 0;
285 3290           key->pool = NULL;
286 3290           }
287              
288             /* 'to' key digits are allocated here */
289 128           int32_t psRsaCopyKey(psRsaKey_t *to, const psRsaKey_t *from)
290             {
291 128           int32_t err = 0;
292              
293 128 50         if ((err = pstm_init_copy(from->pool, &to->N, &from->N, 0)) != PSTM_OKAY)
294             {
295 0           goto error;
296             }
297 128 50         if ((err = pstm_init_copy(from->pool, &to->e, &from->e, 0)) != PSTM_OKAY)
298             {
299 0           goto error;
300             }
301 128 50         if ((err = pstm_init_copy(from->pool, &to->d, &from->d, 0)) != PSTM_OKAY)
302             {
303 0           goto error;
304             }
305 128 50         if ((err = pstm_init_copy(from->pool, &to->p, &from->p, 0)) != PSTM_OKAY)
306             {
307 0           goto error;
308             }
309 128 50         if ((err = pstm_init_copy(from->pool, &to->q, &from->q, 0)) != PSTM_OKAY)
310             {
311 0           goto error;
312             }
313 128 50         if ((err = pstm_init_copy(from->pool, &to->dP, &from->dP, 0)) != PSTM_OKAY)
314             {
315 0           goto error;
316             }
317 128 50         if ((err = pstm_init_copy(from->pool, &to->dQ, &from->dQ, 0)) != PSTM_OKAY)
318             {
319 0           goto error;
320             }
321 128 50         if ((err = pstm_init_copy(from->pool, &to->qP, &from->qP, 0)) != PSTM_OKAY)
322             {
323 0           goto error;
324             }
325 128           to->size = from->size;
326 128           to->optimized = from->optimized;
327 128           to->pool = from->pool;
328             error:
329 128 50         if (err < 0)
330             {
331 0           psRsaClearKey(to);
332             }
333 128           return err;
334             }
335             #endif /* USE_MATRIX_RSA */
336              
337             #ifdef USE_RSA
338             /******************************************************************************/
339             /**
340             Get the size in bytes of the RSA public exponent.
341             Eg. 128 for 1024 bit RSA keys, 256 for 2048 and 512 for 4096 bit keys.
342             @param[in] key RSA key
343             @return Number of bytes of public exponent.
344             */
345 3153           psSize_t psRsaSize(const psRsaKey_t *key)
346             {
347 3153           return key->size;
348             }
349              
350             /******************************************************************************/
351             /**
352             Compare if the public modulus and exponent is the same between two keys.
353              
354             @return < 0 on failure, >= 0 on success.
355             */
356 250           int32_t psRsaCmpPubKey(const psRsaKey_t *k1, const psRsaKey_t *k2)
357             {
358 500           if ((pstm_cmp(&k1->N, &k2->N) == PSTM_EQ) &&
359 250           (pstm_cmp(&k1->e, &k2->e) == PSTM_EQ))
360             {
361 250           return PS_SUCCESS;
362             }
363 0           return PS_FAIL;
364             }
365              
366             # ifdef OLD
367             /******************************************************************************/
368             /*
369             */
370             static int32_t getBig(psPool_t *pool, const unsigned char **pp, psSize_t len,
371             pstm_int *big)
372             {
373             const unsigned char *p = *pp;
374             psSize_t vlen;
375              
376             if (len < 1 || *(p++) != ASN_INTEGER ||
377             getAsnLength(&p, len - 1, &vlen) < 0 || (len - 1) < vlen)
378             {
379             return PS_PARSE_FAIL;
380             }
381             /* Make a smart size since we know the length */
382             if (pstm_init_for_read_unsigned_bin(pool, big, vlen) != PSTM_OKAY)
383             {
384             return PS_MEM_FAIL;
385             }
386             if (pstm_read_unsigned_bin(big, p, vlen) != 0)
387             {
388             pstm_clear(big);
389             psTraceCrypto("ASN getBig failed\n");
390             return PS_PARSE_FAIL;
391             }
392             *pp = p + vlen;
393             return PS_SUCCESS;
394             }
395             # endif
396              
397             /******************************************************************************/
398             /**
399             Parse an RSA public key from an ASN.1 byte stream.
400             @return < 0 on error, >= 0 on success.
401             */
402 2774           int32_t psRsaParseAsnPubKey(psPool_t *pool,
403             const unsigned char **pp, psSize_t len,
404             psRsaKey_t *key, unsigned char sha1KeyHash[SHA1_HASH_SIZE])
405             {
406             # ifdef USE_SHA1
407             psDigestContext_t dc;
408             # endif
409 2774           const unsigned char *p = *pp;
410             const unsigned char *end;
411             psSize_t keylen, seqlen;
412              
413 5548 50         if (len < 1 || (*(p++) != ASN_BIT_STRING) ||
414 5548 50         getAsnLength(&p, len - 1, &keylen) < 0 ||
415 2774           (len - 1) < keylen)
416             {
417             goto L_FAIL;
418             }
419 2774 50         if (*p++ != 0)
420             {
421 0           goto L_FAIL;
422             }
423 2774 50         if (keylen < 1)
424             {
425 0           goto L_FAIL;
426             }
427             # ifdef USE_SHA1
428             /* A public key hash is used in PKI tools (OCSP, Trusted CA indication).
429             Standard RSA form - SHA-1 hash of the value of the BIT STRING
430             subjectPublicKey [excluding the tag, length, and number of unused
431             bits] */
432 2774           psSha1PreInit(&dc.sha1);
433 2774           psSha1Init(&dc.sha1);
434 2774           psSha1Update(&dc.sha1, p, keylen - 1);
435 2774           psSha1Final(&dc.sha1, sha1KeyHash);
436             # endif
437              
438 2774 50         if (getAsnSequence(&p, keylen, &seqlen) < 0)
439             {
440 0           goto L_FAIL;
441             }
442              
443 2774           end = p + seqlen;
444 5548           if (pstm_read_asn(pool, &p, (uint16_t) (end - p), &key->N) < 0 ||
445 2774           pstm_read_asn(pool, &p, (uint16_t) (end - p), &key->e) < 0)
446             {
447              
448             goto L_FAIL;
449             }
450 2774           key->size = pstm_unsigned_bin_size(&key->N);
451 2774           key->pool = pool;
452             # ifdef USE_TILERA_RSA
453             # ifdef USE_RSA_PUBLIC_NONBLOCKING
454             key->nonBlock = 1;
455             # else
456             key->nonBlock = 0;
457             # endif
458             # endif
459 2774           *pp = p;
460 2774           return PS_SUCCESS;
461             L_FAIL:
462             psTraceIntCrypto("psRsaReadAsnPubKey error on byte %d\n", p - *pp);
463 2774           return PS_PARSE_FAIL;
464             }
465              
466             # ifdef USE_PRIVATE_KEY_PARSING
467             /******************************************************************************/
468             /**
469             Parse a a private key structure in DER formatted ASN.1
470             Per ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
471             RSAPrivateKey ::= SEQUENCE {
472             version Version,
473             modulus INTEGER, -- n
474             publicExponent INTEGER, -- e
475             privateExponent INTEGER, -- d
476             prime1 INTEGER, -- p
477             prime2 INTEGER, -- q
478             exponent1 INTEGER, -- d mod (p-1)
479             exponent2 INTEGER, -- d mod (q-1)
480             coefficient INTEGER, -- (inverse of q) mod p
481             otherPrimeInfos OtherPrimeInfos OPTIONAL
482             }
483             Version ::= INTEGER { two-prime(0), multi(1) }
484             (CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
485              
486             Which should look something like this in hex (pipe character
487             is used as a delimiter):
488             ftp://ftp.rsa.com/pub/pkcs/ascii/layman.asc
489             30 Tag in binary: 00|1|10000 -> UNIVERSAL | CONSTRUCTED | SEQUENCE (16)
490             82 Length in binary: 1 | 0000010 -> LONG LENGTH | LENGTH BYTES (2)
491             04 A4 Length Bytes (1188)
492             02 Tag in binary: 00|0|00010 -> UNIVERSAL | PRIMITIVE | INTEGER (2)
493             01 Length in binary: 0|0000001 -> SHORT LENGTH | LENGTH (1)
494             00 INTEGER value (0) - RSAPrivateKey.version
495             02 Tag in binary: 00|0|00010 -> UNIVERSAL | PRIMITIVE | INTEGER (2)
496             82 Length in binary: 1 | 0000010 -> LONG LENGTH | LENGTH BYTES (2)
497             01 01 Length Bytes (257)
498             [] 257 Bytes of data - RSAPrivateKey.modulus (2048 bit key)
499             02 Tag in binary: 00|0|00010 -> UNIVERSAL | PRIMITIVE | INTEGER (2)
500             03 Length in binary: 0|0000011 -> SHORT LENGTH | LENGTH (3)
501             01 00 01 INTEGER value (65537) - RSAPrivateKey.publicExponent
502             ...
503              
504             OtherPrimeInfos is not supported in this routine, and an error will be
505             returned if they are present
506              
507             @return < 0 on error, >= 0 on success.
508             */
509 383           int32_t psRsaParsePkcs1PrivKey(psPool_t *pool,
510             const unsigned char *p, psSize_t size,
511             psRsaKey_t *key)
512             {
513             const unsigned char *end, *seq;
514             int32_t version;
515             psSize_t seqlen;
516              
517 383 50         if (psRsaInitKey(pool, key) < 0)
518             {
519 0           return PS_MEM_FAIL;
520             }
521 383           end = p + size;
522 383 100         if (getAsnSequence(&p, size, &seqlen) < 0)
523             {
524 2           psRsaClearKey(key);
525 2           return PS_PARSE_FAIL;
526             }
527 381           seq = p;
528 762 50         if (getAsnInteger(&p, (uint16_t) (end - p), &version) < 0 || version != 0 ||
529 632 50         pstm_read_asn(pool, &p, (uint16_t) (end - p), &(key->N)) < 0 ||
530 502 50         pstm_read_asn(pool, &p, (uint16_t) (end - p), &(key->e)) < 0 ||
531 502 50         pstm_read_asn(pool, &p, (uint16_t) (end - p), &(key->d)) < 0 ||
532 502 50         pstm_read_asn(pool, &p, (uint16_t) (end - p), &(key->p)) < 0 ||
533 502 50         pstm_read_asn(pool, &p, (uint16_t) (end - p), &(key->q)) < 0 ||
534 502 50         pstm_read_asn(pool, &p, (uint16_t) (end - p), &(key->dP)) < 0 ||
535 502 50         pstm_read_asn(pool, &p, (uint16_t) (end - p), &(key->dQ)) < 0 ||
536 502 50         pstm_read_asn(pool, &p, (uint16_t) (end - p), &(key->qP)) < 0 ||
537 251           (uint16_t) (p - seq) != seqlen)
538             {
539              
540             psTraceCrypto("ASN RSA private key extract parse error\n");
541 130           psRsaClearKey(key);
542 130           return PS_PARSE_FAIL;
543             }
544              
545             # ifdef USE_TILERA_RSA
546             /* EIP-54 usage limitation that some operands must be larger than others.
547             If you are seeing RSA unpad failures after decryption, try toggling
548             this swap. It does seem to work 100% of the time by either performing
549             or not performing this swap. */
550             /* EIP-24 requires dP > dQ. Swap and recalc qP */
551             if (pstm_cmp_mag(&key->p, &key->q) == PSTM_LT)
552             {
553             pstm_exch(&key->dP, &key->dQ);
554             pstm_exch(&key->p, &key->q);
555             pstm_zero(&key->qP);
556             pstm_invmod(pool, &key->q, &key->p, &key->qP);
557             }
558             # ifdef USE_RSA_PRIVATE_NONBLOCKING
559             key->nonBlock = 1;
560             # else
561             key->nonBlock = 0;
562             # endif
563             # endif /* USE_TILERA_RSA */
564              
565             /*
566             If we made it here, the key is ready for optimized decryption
567             Set the key length of the key
568             */
569 251           key->optimized = 1;
570 251           key->size = pstm_unsigned_bin_size(&key->N);
571              
572             /* Should be at the end */
573 251 100         if (end != p)
574             {
575             /* If this stream came from an encrypted file, there could be
576             padding bytes on the end */
577 1           seqlen = (uint16_t) (end - p);
578 9 100         while (p < end)
579             {
580 8           if (*p != seqlen)
581             {
582             psTraceCrypto("Problem at end of private key parse\n");
583             }
584 8           p++;
585             }
586             }
587              
588 383           return PS_SUCCESS;
589             }
590             # endif /* USE_PRIVATE_KEY_PARSING */
591             #endif /* USE_RSA */
592              
593             #ifdef USE_MATRIX_RSA
594             /******************************************************************************/
595             /**
596             Primary RSA crypto routine, with either public or private key.
597              
598             @param[in] pool Pool to use for temporary memory allocation for this op.
599             @param[in] key RSA key to use for this operation.
600             @param[in] in Pointer to allocated buffer to encrypt.
601             @param[in] inlen Number of bytes pointed to by 'in' to encrypt.
602             @param[out] out Pointer to allocated buffer to store encrypted data.
603             @param[out] outlen Number of bytes written to 'out' buffer.
604             @param[in] type PS_PRIVKEY or PS_PUBKEY.
605             @param[in] data TODO Hardware context.
606              
607             @return 0 on success, < 0 on failure.
608              
609             @note 'out' and 'in' can be equal for in-situ operation.
610             */
611 4501           int32_t psRsaCrypt(psPool_t *pool, psRsaKey_t *key,
612             const unsigned char *in, psSize_t inlen,
613             unsigned char *out, psSize_t *outlen,
614             uint8_t type, void *data)
615             {
616             pstm_int tmp, tmpa, tmpb;
617             int32_t res;
618             uint32_t x;
619              
620 4501 50         if (in == NULL || out == NULL || outlen == NULL || key == NULL)
    50          
    50          
    50          
621             {
622             psTraceCrypto("NULL parameter error in psRsaCrypt\n");
623 0           return PS_ARG_FAIL;
624             }
625              
626 4501           tmp.dp = tmpa.dp = tmpb.dp = NULL;
627              
628             /* Init and copy into tmp */
629 4501 50         if (pstm_init_for_read_unsigned_bin(pool, &tmp, inlen + sizeof(pstm_digit))
630             != PS_SUCCESS)
631             {
632 0           return PS_FAILURE;
633             }
634 4501 50         if (pstm_read_unsigned_bin(&tmp, (unsigned char *) in, inlen) != PS_SUCCESS)
635             {
636 0           pstm_clear(&tmp);
637 0           return PS_FAILURE;
638             }
639             /* Sanity check on the input */
640 4501 50         if (pstm_cmp(&key->N, &tmp) == PSTM_LT)
641             {
642 0           res = PS_LIMIT_FAIL;
643 0           goto done;
644             }
645 4501 100         if (type == PS_PRIVKEY)
646             {
647 1147 50         if (key->optimized)
648             {
649 1147 50         if (pstm_init_size(pool, &tmpa, key->p.alloc) != PS_SUCCESS)
650             {
651 0           res = PS_FAILURE;
652 0           goto done;
653             }
654 1147 50         if (pstm_init_size(pool, &tmpb, key->q.alloc) != PS_SUCCESS)
655             {
656 0           pstm_clear(&tmpa);
657 0           res = PS_FAILURE;
658 0           goto done;
659             }
660 1147 50         if (pstm_exptmod(pool, &tmp, &key->dP, &key->p, &tmpa) !=
661             PS_SUCCESS)
662             {
663             psTraceCrypto("decrypt error: pstm_exptmod dP, p\n");
664 0           goto error;
665             }
666 1147 50         if (pstm_exptmod(pool, &tmp, &key->dQ, &key->q, &tmpb) !=
667             PS_SUCCESS)
668             {
669             psTraceCrypto("decrypt error: pstm_exptmod dQ, q\n");
670 0           goto error;
671             }
672 1147 50         if (pstm_sub(&tmpa, &tmpb, &tmp) != PS_SUCCESS)
673             {
674             psTraceCrypto("decrypt error: sub tmpb, tmp\n");
675 0           goto error;
676             }
677 1147 50         if (pstm_mulmod(pool, &tmp, &key->qP, &key->p, &tmp) != PS_SUCCESS)
678             {
679             psTraceCrypto("decrypt error: pstm_mulmod qP, p\n");
680 0           goto error;
681             }
682 1147 50         if (pstm_mul_comba(pool, &tmp, &key->q, &tmp, NULL, 0)
683             != PS_SUCCESS)
684             {
685             psTraceCrypto("decrypt error: pstm_mul q \n");
686 0           goto error;
687             }
688 1147 50         if (pstm_add(&tmp, &tmpb, &tmp) != PS_SUCCESS)
689             {
690             psTraceCrypto("decrypt error: pstm_add tmp \n");
691 0           goto error;
692             }
693             }
694             else
695             {
696 0 0         if (pstm_exptmod(pool, &tmp, &key->d, &key->N, &tmp) !=
697             PS_SUCCESS)
698             {
699             psTraceCrypto("psRsaCrypt error: pstm_exptmod\n");
700 0           goto error;
701             }
702             }
703             }
704 3354 50         else if (type == PS_PUBKEY)
705             {
706 3354 50         if (pstm_exptmod(pool, &tmp, &key->e, &key->N, &tmp) != PS_SUCCESS)
707             {
708             psTraceCrypto("psRsaCrypt error: pstm_exptmod\n");
709 0           goto error;
710             }
711             }
712             else
713             {
714             psTraceCrypto("psRsaCrypt error: invalid type param\n");
715 0           goto error;
716             }
717             /* Read it back */
718 4501           x = pstm_unsigned_bin_size(&key->N);
719              
720 4501 50         if ((uint32) x > *outlen)
721             {
722 0           res = -1;
723             psTraceCrypto("psRsaCrypt error: pstm_unsigned_bin_size\n");
724 0           goto done;
725             }
726             /* We want the encrypted value to always be the key size. Pad with 0x0 */
727 4501 50         while ((uint32) x < (unsigned long) key->size)
728             {
729 0           *out++ = 0x0;
730 0           x++;
731             }
732              
733 4501           *outlen = x;
734             /* Convert it */
735 4501           memset(out, 0x0, x);
736              
737 4501 50         if (pstm_to_unsigned_bin(pool, &tmp, out + (x - pstm_unsigned_bin_size(&tmp)))
738             != PS_SUCCESS)
739             {
740             psTraceCrypto("psRsaCrypt error: pstm_to_unsigned_bin\n");
741 0           goto error;
742             }
743             /* Clean up and return */
744 4501           res = PS_SUCCESS;
745 4501           goto done;
746             error:
747 0           res = PS_FAILURE;
748             done:
749 4501 100         if (type == PS_PRIVKEY && key->optimized)
    50          
750             {
751 1147           pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL);
752             }
753 4501           pstm_clear(&tmp);
754 4501           return res;
755             }
756              
757             /******************************************************************************/
758             /**
759             RSA private encryption. This is used by a private key holder to sign
760             data that can be verified by psRsaDecryptPub().
761              
762             @param[in] pool Pool to use for temporary memory allocation for this op.
763             @param[in] key RSA key to use for this operation.
764             @param[in] in Pointer to allocated buffer to encrypt.
765             @param[in] inlen Number of bytes pointed to by 'in' to encrypt.
766             @param[out] out Pointer to allocated buffer to store encrypted data.
767             @param[out] outlen Number of bytes written to 'out' buffer.
768             @param[in] data TODO Hardware context.
769              
770             @return 0 on success, < 0 on failure.
771             */
772 1146           int32_t psRsaEncryptPriv(psPool_t *pool, psRsaKey_t *key,
773             const unsigned char *in, psSize_t inlen,
774             unsigned char *out, psSize_t outlen,
775             void *data)
776             {
777 1146           unsigned char *verify = NULL;
778 1146           unsigned char *tmpout = NULL;
779             int32_t err;
780             psSize_t size, olen;
781              
782             /** @security We follow the FIPS 186 recommendation for minimum data to sign. */
783 1146 50         if (inlen < 28)
784             {
785             psTraceCrypto("Error inlen < 28 bytes in psRsaEncryptPriv\n");
786 0           return PS_ARG_FAIL;
787             }
788 1146           size = key->size;
789 1146 50         if (outlen < size)
790             {
791             psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPriv\n");
792 0           return PS_ARG_FAIL;
793             }
794 1146           olen = outlen; /* Save in case we zero 'out' later */
795 1146 50         if ((err = pkcs1Pad(in, inlen, out, size, PS_PUBKEY, data)) < PS_SUCCESS)
796             {
797             psTraceCrypto("Error padding psRsaEncryptPriv. Likely data too long\n");
798 0           return err;
799             }
800 1146 50         if ((err = psRsaCrypt(pool, key, out, size, out, &outlen,
801             PS_PRIVKEY, data)) < PS_SUCCESS)
802             {
803             psTraceCrypto("Error performing psRsaEncryptPriv\n");
804 0           return err;
805             }
806 1146 50         if (outlen != size)
807             {
808 0           goto L_FAIL;
809             }
810              
811             /**
812             @security Verify the signature we just made before it is used
813             by the caller. If the signature is invalid for some reason
814             (hardware or software error or memory overrun), it can
815             leak information on the private key.
816             */
817 1146 50         if ((verify = psMalloc(pool, inlen)) == NULL)
818             {
819 0           goto L_FAIL;
820             }
821             /* psRsaDecryptPub overwrites the input, so duplicate it here */
822 1146 50         if ((tmpout = psMalloc(pool, outlen)) == NULL)
823             {
824 0           goto L_FAIL;
825             }
826 1146           memcpy(tmpout, out, outlen);
827 1146 50         if (psRsaDecryptPub(pool, key,
828             tmpout, outlen, verify, inlen, data) < 0)
829             {
830 0           goto L_FAIL;
831             }
832 1146 50         if (memcmpct(in, verify, inlen) != 0)
833             {
834 0           goto L_FAIL;
835             }
836 1146           memzero_s(verify, inlen);
837 1146           psFree(verify, pool);
838 1146           memzero_s(tmpout, outlen);
839 1146           psFree(tmpout, pool);
840              
841 1146           return PS_SUCCESS;
842              
843             L_FAIL:
844 0           memzero_s(out, olen); /* Clear, to ensure bad result isn't used */
845 0 0         if (tmpout)
846             {
847 0           memzero_s(tmpout, outlen);
848 0           psFree(tmpout, pool);
849             }
850 0 0         if (verify)
851             {
852 0           memzero_s(verify, inlen);
853 0           psFree(verify, pool);
854             }
855             psTraceCrypto("Signature mismatch in psRsaEncryptPriv\n");
856 0           return PS_FAIL;
857             }
858              
859             /******************************************************************************/
860             /**
861             RSA public encryption. This is used by a public key holder to do
862             key exchange with the private key holder, which can access the key using
863             psRsaDecryptPriv().
864              
865             @param[in] pool Pool to use for temporary memory allocation for this op.
866             @param[in] key RSA key to use for this operation.
867             @param[in] in Pointer to allocated buffer to encrypt.
868             @param[in] inlen Number of bytes pointed to by 'in' to encrypt.
869             @param[out] out Pointer to allocated buffer to store encrypted data.
870             @param[in] expected output length
871             @param[in] data TODO Hardware context.
872              
873             @return 0 on success, < 0 on failure.
874             */
875 1           int32_t psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
876             const unsigned char *in, psSize_t inlen,
877             unsigned char *out, psSize_t outlen,
878             void *data)
879             {
880             int32_t err;
881             psSize_t size;
882              
883 1           size = key->size;
884 1 50         if (outlen < size)
885             {
886             psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n");
887 0           return PS_ARG_FAIL;
888             }
889              
890 1 50         if ((err = pkcs1Pad(in, inlen, out, size, PS_PRIVKEY, data))
891             < PS_SUCCESS)
892             {
893             psTraceCrypto("Error padding psRsaEncryptPub. Likely data too long\n");
894 0           return err;
895             }
896 1 50         if ((err = psRsaCrypt(pool, key, out, size, out, &outlen,
897             PS_PUBKEY, data)) < PS_SUCCESS)
898             {
899             psTraceCrypto("Error performing psRsaEncryptPub\n");
900 0           return err;
901             }
902 1 50         if (outlen != size)
903             {
904             psTraceCrypto("Encrypted size error in psRsaEncryptPub\n");
905 0           return PS_FAILURE;
906             }
907 1           return PS_SUCCESS;
908             }
909              
910             /******************************************************************************/
911             /**
912             RSA private decryption. This is used by a private key holder to decrypt
913             a key exchange with the public key holder, which encodes the key using
914             psRsaEncryptPub().
915              
916             @param[in] pool Pool to use for temporary memory allocation for this op.
917             @param[in] key RSA key to use for this operation.
918             @param[in,out] in Pointer to allocated buffer to encrypt.
919             @param[in] inlen Number of bytes pointed to by 'in' to encrypt.
920             @param[out] out Pointer to allocated buffer to store encrypted data.
921             @param[out] outlen Number of bytes written to 'out' buffer.
922             @param[in] data TODO Hardware context.
923              
924             @return 0 on success, < 0 on failure.
925              
926             TODO -fix
927             @note this function writes over the 'in' buffer
928             */
929 1           int32_t psRsaDecryptPriv(psPool_t *pool, psRsaKey_t *key,
930             unsigned char *in, psSize_t inlen,
931             unsigned char *out, psSize_t outlen,
932             void *data)
933             {
934             int32_t err;
935             psSize_t ptLen;
936              
937 1 50         if (inlen != key->size)
938             {
939             psTraceCrypto("Error on bad inlen parameter to psRsaDecryptPriv\n");
940 0           return PS_ARG_FAIL;
941             }
942 1           ptLen = inlen;
943 1 50         if ((err = psRsaCrypt(pool, key, in, inlen, in, &ptLen,
944             PS_PRIVKEY, data)) < PS_SUCCESS)
945             {
946             psTraceCrypto("Error performing psRsaDecryptPriv\n");
947 0           return err;
948             }
949 1 50         if (ptLen != inlen)
950             {
951             psTraceCrypto("Decrypted size error in psRsaDecryptPriv\n");
952 0           return PS_FAILURE;
953             }
954 1           err = pkcs1Unpad(in, inlen, out, outlen, PS_PRIVKEY);
955 1           memset(in, 0x0, inlen);
956 1           return err;
957             }
958              
959             /******************************************************************************/
960             /**
961             RSA public decryption. This is used by a public key holder to verify
962             a signature by the private key holder, who signs using psRsaEncryptPriv().
963              
964             @param[in] pool Pool to use for temporary memory allocation for this op.
965             @param[in] key RSA key to use for this operation.
966             @param[in,out] in Pointer to allocated buffer to encrypt.
967             @param[in] inlen Number of bytes pointed to by 'in' to encrypt.
968             @param[out] out Pointer to allocated buffer to store encrypted data.
969             @param[in] outlen length of expected output.
970             @param[in] data TODO Hardware context.
971              
972             @return 0 on success, < 0 on failure.
973              
974             TODO -fix
975             @note this function writes over the 'in' buffer
976             */
977 3353           int32_t psRsaDecryptPub(psPool_t *pool, psRsaKey_t *key,
978             unsigned char *in, psSize_t inlen,
979             unsigned char *out, psSize_t outlen,
980             void *data)
981             {
982             int32_t err;
983             psSize_t ptLen;
984              
985 3353 50         if (inlen != key->size)
986             {
987             psTraceCrypto("Error on bad inlen parameter to psRsaDecryptPub\n");
988 0           return PS_ARG_FAIL;
989             }
990 3353           ptLen = inlen;
991 3353 50         if ((err = psRsaCrypt(pool, key, in, inlen, in, &ptLen,
992             PS_PUBKEY, data)) < PS_SUCCESS)
993             {
994             psTraceCrypto("Error performing psRsaDecryptPub\n");
995 0           return err;
996             }
997 3353 50         if (ptLen != inlen)
998             {
999             psTraceIntCrypto("Decrypted size error in psRsaDecryptPub %d\n", ptLen);
1000 0           return PS_FAILURE;
1001             }
1002 3353 50         if ((err = pkcs1Unpad(in, inlen, out, outlen, PS_PUBKEY)) < 0)
1003             {
1004 0           return err;
1005             }
1006 3353           return PS_SUCCESS;
1007             }
1008              
1009             #endif /* USE_MATRIX_RSA */
1010              
1011             /******************************************************************************/
1012