File Coverage

inc/matrixssl-3-9-3-open/crypto/pubkey/pubkey.c
Criterion Covered Total %
statement 27 192 14.0
branch 4 76 5.2
condition n/a
subroutine n/a
pod n/a
total 31 268 11.5


line stmt bran cond sub pod time code
1             /**
2             * @file pubkey.c
3             * @version 950bba4 (HEAD -> master)
4             *
5             * Public and Private key operations shared by crypto implementations.
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             #if defined(USE_RSA) || defined(USE_ECC)
38              
39             /******************************************************************************/
40              
41 3125           int32_t psInitPubKey(psPool_t *pool, psPubKey_t *key, uint8_t type)
42             {
43 3125 50         if (!key)
44             {
45 0           return PS_ARG_FAIL;
46             }
47 3125           switch (type)
48             {
49             # ifdef USE_RSA
50             case PS_RSA:
51 3020           psRsaInitKey(pool, &key->key.rsa);
52 3020           break;
53             # endif
54             # ifdef USE_ECC
55             case PS_ECC:
56 105           psEccInitKey(pool, &key->key.ecc, NULL);
57 105           break;
58             # endif
59             default:
60 0           break;
61             }
62 3125           key->pool = pool;
63 3125           key->type = type;
64 3125           key->keysize = 0;
65 3125           return PS_SUCCESS;
66             }
67              
68             /******************************************************************************/
69              
70 100944           void psClearPubKey(psPubKey_t *key)
71             {
72 100944 50         if (!key)
73             {
74 0           return;
75             }
76 100944           switch (key->type)
77             {
78             # ifdef USE_RSA
79             case PS_RSA:
80 384           psRsaClearKey(&key->key.rsa);
81 384           break;
82             # endif
83             # ifdef USE_ECC
84             case PS_ECC:
85 0           psEccClearKey(&key->key.ecc);
86 0           break;
87             # endif
88             default:
89 100560           break;
90             }
91 100944           key->pool = NULL;
92 100944           key->keysize = 0;
93 100944           key->type = 0;
94             }
95              
96 0           int32_t psNewPubKey(psPool_t *pool, uint8_t type, psPubKey_t **key)
97             {
98             int32_t rc;
99              
100 0 0         if ((*key = psMalloc(pool, sizeof(psPubKey_t))) == NULL)
101             {
102 0           return PS_MEM_FAIL;
103             }
104              
105 0 0         if ((rc = psInitPubKey(pool, *key, type)) < 0)
106             {
107 0           psFree(*key, pool);
108             }
109 0           return rc;
110             }
111              
112 0           void psDeletePubKey(psPubKey_t **key)
113             {
114 0           psClearPubKey(*key);
115 0           psFree(*key, NULL);
116 0           *key = NULL;
117 0           }
118              
119             # ifdef USE_PRIVATE_KEY_PARSING
120             # ifdef MATRIX_USE_FILE_SYSTEM
121             # if defined(USE_ECC) && defined(USE_RSA)
122             /*
123             Trial and error private key parse for when ECC or RSA is unknown.
124             keyBuf must point to a buffer of length keyBufLen, containing
125             a DER-encoded key.
126              
127             Return codes:
128             1 RSA key
129             2 ECC key
130             < 0 error
131             */
132 0           int32_t psParseUnknownPrivKeyMem(psPool_t *pool,
133             unsigned char *keyBuf, int32 keyBufLen,
134             const char *password, psPubKey_t *privkey)
135             {
136             psRsaKey_t *rsakey;
137             psEccKey_t *ecckey;
138 0           int32_t keytype = 1;
139             psBool_t notRsaKey;
140              
141 0 0         if (keyBuf == NULL || keyBufLen <= 0)
    0          
142 0           return PS_ARG_FAIL;
143              
144 0           privkey->keysize = 0;
145 0           rsakey = &privkey->key.rsa;
146 0           ecckey = &privkey->key.ecc;
147              
148             /* Examine data to ensure parses which could not succeed are not tried. */
149            
150             /* Guess if this can be RSA key based on length of encoding and content.
151             Even the smallest (obsolete 512-bit modulus) RSA private keys are >
152             256 bytes.
153             */
154 0 0         notRsaKey = keyBufLen < 257 || keyBuf[0] != 0x30 || keyBuf[1] < 0x82;
    0          
    0          
155              
156             /* A raw RSAPrivateKey? */
157 0           if (notRsaKey != PS_FALSE ||
158 0           psRsaParsePkcs1PrivKey(pool, keyBuf, keyBufLen, rsakey)
159             < PS_SUCCESS)
160             {
161             /* A raw ECPrivateKey? */
162 0 0         if (psEccParsePrivKey(pool, keyBuf, keyBufLen, ecckey, NULL)
163             < PS_SUCCESS)
164             {
165             # ifdef USE_PKCS8
166             /* A PKCS #8 PrivateKeyInfo containing an ECPrivateKey? */
167 0 0         if (psPkcs8ParsePrivBin(pool, keyBuf, keyBufLen,
168             (char*)password, privkey))
169             {
170             # endif /* USE_PKCS8 */
171             /* Nothing worked. */
172             psTraceCrypto("Unable to parse private key. " \
173             "Supported formats are RSAPrivateKey, " \
174             "ECPrivateKey and PKCS #8.\n");
175 0           return PS_FAILURE;
176             # ifdef USE_PKCS8
177             }
178 0 0         if (privkey->type == PS_RSA)
179             {
180 0           keytype = 1;
181             }
182 0 0         else if (privkey->type == PS_ECC)
183             {
184 0           keytype = 2;
185             }
186 0           goto parsed;
187             # endif /* USE_PKCS8 */
188             }
189 0           keytype = 2;
190             }
191              
192             # ifdef USE_PKCS8
193             parsed:
194             # endif /* USE_PKCS8 */
195 0 0         if (keytype == 1)
196             {
197 0           privkey->type = PS_RSA;
198 0           privkey->keysize = psRsaSize(&privkey->key.rsa);
199             }
200             else
201             {
202 0           privkey->type = PS_ECC;
203 0           privkey->keysize = psEccSize(&privkey->key.ecc);
204             }
205 0           privkey->pool = pool;
206              
207 0           return keytype;
208             }
209              
210             /* Trial and error private key parse for when ECC or RSA is unknown.
211              
212             pemOrDer should be 1 if PEM
213              
214             Return codes:
215             1 RSA key
216             2 ECC key
217             < 0 error
218             */
219 0           int32_t psParseUnknownPrivKey(psPool_t *pool, int pemOrDer,
220             const char *keyfile, const char *password,
221             psPubKey_t *privkey)
222             {
223             psRsaKey_t *rsakey;
224             psEccKey_t *ecckey;
225 0           int keytype = 1;
226             unsigned char *keyBuf;
227             int32 keyBufLen;
228             int32_t rc;
229              
230 0           privkey->keysize = 0;
231 0           rsakey = &privkey->key.rsa;
232 0           ecckey = &privkey->key.ecc;
233 0 0         if (pemOrDer == 1)
234             {
235             /* PEM file. */
236 0 0         if (psPkcs1ParsePrivFile(pool, keyfile, password, rsakey)
237             < PS_SUCCESS)
238             {
239             /* psEccParsePrivFile will also try psPkcs8ParsePrivBin. */
240 0 0         if (psEccParsePrivFile(pool, keyfile, password, ecckey)
241             < PS_SUCCESS)
242             {
243             psTraceStrCrypto("Unable to parse private key file %s\n",
244             keyfile);
245 0           return PS_FAILURE;
246             }
247 0           keytype = 2;
248             }
249             else
250             {
251 0           keytype = 1;
252             }
253             }
254             else
255             {
256             /* DER file. */
257 0 0         if (psGetFileBuf(pool, keyfile, &keyBuf, &keyBufLen) < PS_SUCCESS)
258             {
259             psTraceStrCrypto("Unable to open private key file %s\n", keyfile);
260 0           return -1;
261             }
262 0           rc = psParseUnknownPrivKeyMem(pool, keyBuf, keyBufLen, password,
263             privkey);
264 0           psFree(keyBuf, pool);
265              
266             /* Continue examining result of private key parsing. */
267 0 0         if (rc < 0)
268             {
269             psTraceStrCrypto("Unable to parse private key file %s\n", keyfile);
270 0           return -1;
271             }
272 0           keytype = rc;
273 0           goto out; /* psParseUnknownPrivKeyMem already set up everything. */
274             }
275              
276 0 0         if (keytype == 1)
277             {
278 0           privkey->type = PS_RSA;
279 0           privkey->keysize = psRsaSize(&privkey->key.rsa);
280             }
281             else
282             {
283 0           privkey->type = PS_ECC;
284 0           privkey->keysize = psEccSize(&privkey->key.ecc);
285             }
286 0           privkey->pool = pool;
287             out:
288 0           return keytype;
289             }
290              
291             /* Trial and error public key parse for when ECC or RSA is unknown.
292              
293             pemOrDer should be 1 if PEM
294              
295             Note: The current version of this function only supports RSA when
296             MatrixSSL's stock cryptographic library is used and
297             additionally ECC when CL cryptographic library is used.
298              
299             Return codes:
300             1 RSA key
301             2 ECC key
302             -1 error
303             */
304 0           int32_t psParseUnknownPubKey(psPool_t *pool, int pemOrDer, char *keyfile,
305             const char *password, psPubKey_t *pubkey)
306             {
307             psRsaKey_t *rsakey;
308 0           int keytype = 1;
309             unsigned char *keyBuf;
310             int32 keyBufLen;
311              
312             /* flps_parseUnknownPubKey() is similar function.
313             First try to invoke that. */
314              
315             (void) password; /* password is for future extensions. */
316 0           pubkey->keysize = 0;
317 0           rsakey = &pubkey->key.rsa;
318 0 0         if (pemOrDer == 1)
319             {
320             /* PEM file. */
321 0 0         if (psPkcs1ParsePubFile(pool, keyfile, rsakey)
322             < PS_SUCCESS)
323             {
324 0           return PS_FAILURE;
325             }
326              
327 0           pubkey->type = PS_RSA;
328 0           pubkey->keysize = psRsaSize(&pubkey->key.rsa);
329 0           return keytype;
330             }
331             else
332             {
333             /* DER file. */
334 0 0         if (psGetFileBuf(pool, keyfile, &keyBuf, &keyBufLen) < PS_SUCCESS)
335             {
336             psTraceStrCrypto("Unable to open public key file %s\n", keyfile);
337 0           return -1;
338             }
339             /* Processing DER files not handled by current implementation of
340             the function the input shall be in PEM format. */
341 0           psFree(keyBuf, pool);
342 0           return PS_FAILURE;
343             }
344             }
345              
346             # endif /* USE_ECC && USE_RSA */
347             # endif /* MATRIX_USE_FILE_SYSTEM */
348             # endif /* USE_PRIVATE_KEY_PARSING */
349              
350 1057           int32_t psHashLenToSigAlg(psSize_t hash_len,
351             uint8_t key_type)
352             {
353             int32_t signatureAlgorithm;
354              
355             /**/
356 1057 50         psAssert(key_type == PS_RSA || key_type == PS_ECC);
    0          
357              
358 1057           switch (hash_len)
359             {
360             # if defined(USE_MD2) || defined(USE_MD5)
361             case MD2_HASH_SIZE:
362 0 0         if (key_type == PS_RSA)
363             {
364             psTraceCrypto("pubRsaDecryptSignedElement cannot handle ");
365             psTraceCrypto("RSA-MD2 or RSA-MD5 signatures; please use ");
366             psTraceCrypto("pubRsaDecryptSignedElementExt instead.\n");
367 0           return PS_ARG_FAIL;
368             }
369             else
370             {
371             psTraceCrypto("ECDSA-MD2 and ECDSA-MD5 not supported\n");
372 0           return PS_UNSUPPORTED_FAIL;
373             }
374             break;
375             # endif /* USE_MD2 || USE_MD5 */
376             case SHA1_HASH_SIZE:
377 0 0         if (key_type == PS_RSA)
378             {
379 0           signatureAlgorithm = OID_SHA1_RSA_SIG;
380             }
381             else
382             {
383 0           signatureAlgorithm = OID_SHA1_ECDSA_SIG;
384             }
385 0           break;
386             # if 0
387             case SHA224_HASH_SIZE:
388             if (key_type == PS_RSA)
389             {
390             signatureAlgorithm = OID_SHA224_RSA_SIG;
391             }
392             else
393             {
394             signatureAlgorithm = OID_SHA224_ECDSA_SIG;
395             }
396             break;
397             # endif
398             case SHA256_HASH_SIZE:
399 1057 50         if (key_type == PS_RSA)
400             {
401 1057           signatureAlgorithm = OID_SHA256_RSA_SIG;
402             }
403             else
404             {
405 0           signatureAlgorithm = OID_SHA256_ECDSA_SIG;
406             }
407 1057           break;
408             case SHA384_HASH_SIZE:
409 0 0         if (key_type == PS_RSA)
410             {
411 0           signatureAlgorithm = OID_SHA384_RSA_SIG;
412             }
413             else
414             {
415 0           signatureAlgorithm = OID_SHA384_ECDSA_SIG;
416             }
417 0           break;
418             case SHA512_HASH_SIZE:
419 0 0         if (key_type == PS_RSA)
420             {
421 0           signatureAlgorithm = OID_SHA512_RSA_SIG;
422             }
423             else
424             {
425 0           signatureAlgorithm = OID_SHA512_ECDSA_SIG;
426             }
427 0           break;
428             default:
429             psTraceCrypto("Unsupported hash size in RSA signature\n");
430 0           return PS_UNSUPPORTED_FAIL;
431             }
432              
433 1057           return signatureAlgorithm;
434             }
435              
436              
437 0           psRes_t psComputeHashForSig(const unsigned char *dataBegin,
438             psSizeL_t dataLen,
439             int32_t signatureAlgorithm,
440             unsigned char hashOut[SHA512_HASH_SIZE],
441             psSize_t *hashOutLen)
442             {
443             psDigestContext_t hash;
444              
445 0 0         if (hashOut == NULL || hashOutLen == NULL)
    0          
446             {
447 0           return PS_ARG_FAIL;
448             }
449              
450 0 0         if (dataLen < 1)
451             {
452 0           return PS_ARG_FAIL;
453             }
454              
455 0           switch (signatureAlgorithm)
456             {
457             # ifdef ENABLE_MD5_SIGNED_CERTS
458             # ifdef USE_MD2
459             case OID_MD2_RSA_SIG:
460             psMd2Init(&hash.md2);
461             if (psMd2Update(&hash.md2, dataBegin, dataLen) < 0)
462             {
463             return PS_FAILURE;
464             }
465             if (psMd2Final(&hash.md2, hashOut) < 0)
466             {
467             return PS_FAILURE;
468             }
469             *hashOutLen = MD5_HASH_SIZE;
470             break;
471             # endif /* USE_MD2 */
472             case OID_MD5_RSA_SIG:
473             if (psMd5Init(&hash.md5) < 0)
474             {
475             return PS_FAILURE;
476             }
477             psMd5Update(&hash.md5, dataBegin, dataLen);
478             psMd5Final(&hash.md5, hashOut);
479             *hashOutLen = MD5_HASH_SIZE;
480             break;
481             # endif /* ENABLE_MD5_SIGNED_CERTS */
482             case OID_SHA1_RSA_SIG:
483             case OID_SHA1_RSA_SIG2:
484             case OID_SHA1_ECDSA_SIG:
485 0           psSha1PreInit(&hash.sha1);
486 0           psSha1Init(&hash.sha1);
487 0           psSha1Update(&hash.sha1, dataBegin, dataLen);
488 0           psSha1Final(&hash.sha1, hashOut);
489 0           *hashOutLen = SHA1_HASH_SIZE;
490 0           break;
491             #ifdef USE_SHA224
492             case OID_SHA224_RSA_SIG:
493             case OID_SHA224_ECDSA_SIG:
494             psSha224PreInit(&hash.sha256);
495             psSha224Init(&hash.sha256);
496             psSha224Update(&hash.sha256, dataBegin, dataLen);
497             psSha224Final(&hash.sha256, hashOut);
498             *hashOutLen = SHA224_HASH_SIZE;
499             break;
500             #endif /* USE_SHA224 */
501             case OID_SHA256_RSA_SIG:
502             case OID_SHA256_ECDSA_SIG:
503 0           psSha256PreInit(&hash.sha256);
504 0           psSha256Init(&hash.sha256);
505 0           psSha256Update(&hash.sha256, dataBegin, dataLen);
506 0           psSha256Final(&hash.sha256, hashOut);
507 0           *hashOutLen = SHA256_HASH_SIZE;
508 0           break;
509             # ifdef USE_SHA384
510             case OID_SHA384_RSA_SIG:
511             case OID_SHA384_ECDSA_SIG:
512 0           psSha384PreInit(&hash.sha384);
513 0           psSha384Init(&hash.sha384);
514 0           psSha384Update(&hash.sha384, dataBegin, dataLen);
515 0           psSha384Final(&hash.sha384, hashOut);
516 0           *hashOutLen = SHA384_HASH_SIZE;
517 0           break;
518             # endif
519             # ifdef USE_SHA512
520             case OID_SHA512_RSA_SIG:
521             case OID_SHA512_ECDSA_SIG:
522 0           psSha512PreInit(&hash.sha512);
523 0           psSha512Init(&hash.sha512);
524 0           psSha512Update(&hash.sha512, dataBegin, dataLen);
525 0           psSha512Final(&hash.sha512, hashOut);
526 0           *hashOutLen = SHA512_HASH_SIZE;
527 0           break;
528             # endif
529             default:
530             psTraceCrypto("Unsupported sig alg\n");
531 0           return PS_UNSUPPORTED_FAIL;
532             }
533              
534 0           return PS_SUCCESS;
535             }
536              
537 0           psRes_t psVerifySig(psPool_t *pool,
538             const unsigned char hashIn[SHA512_HASH_SIZE],
539             psSize_t hashInLen,
540             const unsigned char *sig,
541             psSize_t sigLen,
542             psPubKey_t *key,
543             int32_t signatureAlgorithm,
544             psBool_t *verifyResult,
545             psVerifySigOptions_t *opts)
546             {
547 0           unsigned char out[SHA512_HASH_SIZE] = { 0 };
548             # ifdef USE_ECC
549             int32 eccRet;
550             # endif
551              
552 0           psRes_t rc = PS_SUCCESS;
553              
554             if (pool == NULL)
555             {
556             }
557              
558 0           *verifyResult = PS_FALSE;
559              
560 0           switch (key->type)
561             {
562             # ifdef USE_RSA
563             case PS_RSA:
564 0 0         if (pubRsaDecryptSignedElementExt(pool, &key->key.rsa,
565             (unsigned char *) sig, sigLen, out,
566             hashInLen, signatureAlgorithm, NULL) < 0)
567             {
568             psTraceCrypto("Error decrypting request signature\n");
569 0           rc = PS_FAILURE;
570 0           goto out;
571             }
572 0 0         if (memcmpct(hashIn, out, hashInLen) != 0)
573             {
574 0           rc = PS_VERIFICATION_FAILED;
575 0           *verifyResult = PS_FALSE;
576 0           goto out;
577             }
578 0           break;
579             # endif /* USE_RSA */
580             # ifdef USE_ECC
581             case PS_ECC:
582 0 0         if (psEccDsaVerify(pool, &key->key.ecc, hashIn,
583             hashInLen, sig, sigLen, &eccRet, NULL) < 0)
584             {
585             psTraceCrypto("Error decrypting request signature\n");
586 0           rc = PS_FAILURE;
587 0           goto out;
588             }
589 0 0         if (eccRet != 1)
590             {
591             psTraceCrypto("Error validating signature\n");
592 0           rc = PS_VERIFICATION_FAILED;
593 0           *verifyResult = PS_FALSE;
594 0           goto out;
595             }
596 0           break;
597             # endif /* USE_ECC */
598             default:
599             psTraceCrypto("Unsupported pubkey algorithm\n");
600 0           rc = PS_UNSUPPORTED_FAIL;
601 0           goto out;
602             }
603              
604 0           *verifyResult = PS_TRUE;
605              
606             out:
607 0           return rc;
608             }
609              
610 0           psRes_t psHashDataAndVerifySig(psPool_t *pool,
611             const unsigned char *dataBegin,
612             const psSizeL_t dataLen,
613             const unsigned char *sig,
614             psSize_t sigLen,
615             psPubKey_t *key,
616             int32_t signatureAlgorithm,
617             psBool_t *verifyResult,
618             psVerifySigOptions_t *opts)
619             {
620 0           unsigned char digest[SHA512_HASH_SIZE] = { 0 };
621 0           psSize_t digestLen = 0;
622             psRes_t rc;
623              
624 0           *verifyResult = PS_FALSE;
625              
626 0           rc = psComputeHashForSig(dataBegin, dataLen,
627             signatureAlgorithm, digest,
628             &digestLen);
629 0 0         if (rc != PS_SUCCESS)
630             {
631 0           return rc;
632             }
633              
634 0           rc = psVerifySig(pool,
635             digest, digestLen,
636             sig, sigLen,
637             key, signatureAlgorithm,
638             verifyResult,
639             opts);
640 0           return rc;
641             }
642              
643             /******************************************************************************/
644              
645             #endif /* USE_RSA || USE_ECC */
646