File Coverage

inc/matrixssl-3-9-3-open/crypto/keyformat/pkcs.c
Criterion Covered Total %
statement 389 1153 33.7
branch 217 760 28.5
condition n/a
subroutine n/a
pod n/a
total 606 1913 31.6


line stmt bran cond sub pod time code
1             /**
2             * @file pkcs.c
3             * @version 950bba4 (HEAD -> master)
4             *
5             * Collection of RSA PKCS standards .
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             /*
39             Pad a value to be encrypted by RSA, according to PKCS#1 v1.5
40             http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
41             When encrypting a value with RSA, the value is first padded to be
42             equal to the public key size using the following method:
43             00 00
44             - id denotes a public or private key operation
45             - if id is private, data is however many non-zero bytes it takes to pad the
46             value to the key length (randomLen = keyLen - 3 - valueLen).
47             - if id is public, data is FF for the same length as described above
48             - There must be at least 8 bytes of data.
49             */
50 1147           int32_t pkcs1Pad(const unsigned char *in, psSize_t inlen,
51             unsigned char *out, psSize_t outlen,
52             uint8_t cryptType, void *userPtr)
53             {
54             unsigned char *c;
55             uint32_t randomLen;
56              
57 1147           randomLen = outlen - 3 - inlen;
58 1147 50         if (randomLen < 8)
59             {
60             psTraceCrypto("pkcs1Pad failure\n");
61 0           return PS_LIMIT_FAIL;
62             }
63 1147           c = out;
64 1147           *c = 0x00;
65 1147           c++;
66 1147           *c = (unsigned char) cryptType;
67 1147           c++;
68 1147 100         if (cryptType == PS_PUBKEY)
69             {
70 232638 100         while (randomLen > 0)
71             {
72 231492           *c++ = 0xFF;
73 231492           randomLen--;
74             }
75             }
76             else
77             {
78 1 50         if (psGetPrngLocked(c, randomLen, userPtr) < 0)
79             {
80 0           return PS_PLATFORM_FAIL;
81             }
82             /*
83             SECURITY: Read through the random data and change all 0x0 to 0x01.
84             This is per spec that no random bytes should be 0
85             */
86 206 100         while (randomLen > 0)
87             {
88 205 100         if (*c == 0x0)
89             {
90 1           *c = 0x01;
91             }
92 205           randomLen--;
93 205           c++;
94             }
95             }
96 1147           *c = 0x00;
97 1147           c++;
98 1147           memcpy(c, in, inlen);
99              
100 1147           return PS_SUCCESS;
101             }
102              
103             /******************************************************************************/
104             /*
105             Unpad a value decrypted by RSA, according to PKCS#1 v1.5
106             http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
107              
108             When decrypted, the data will look like the pad, including the inital
109             byte (00). Form:
110             00 00
111              
112             We don't worry about v2 rollback issues because we don't support v2
113             */
114 3354           int32_t pkcs1Unpad(const unsigned char *in, psSize_t inlen,
115             unsigned char *out, psSize_t outlen,
116             uint8_t decryptType)
117             {
118             const unsigned char *c, *end;
119              
120 3354 50         if (inlen < outlen + 10)
121             {
122             psTraceCrypto("pkcs1Unpad failure\n");
123 0           return PS_ARG_FAIL;
124             }
125 3354           c = in;
126 3354           end = in + inlen;
127              
128             /* Verify the first byte (block type) is correct. */
129 3354 50         if (*c++ != 0x00 || *c != decryptType)
    50          
130             {
131             psTraceCrypto("pkcs1Unpad parse failure\n");
132 0           return PS_FAILURE;
133             }
134 3354           c++;
135              
136             /* Skip over the random, non-zero bytes used as padding */
137 680865 50         while (c < end && *c != 0x0)
    100          
138             {
139 677511 100         if (decryptType == PS_PUBKEY)
140             {
141 677306 50         if (*c != 0xFF)
142             {
143             psTraceCrypto("pkcs1Unpad pubkey parse failure\n");
144 0           return PS_FAILURE;
145             }
146             }
147 677511           c++;
148             }
149 3354           c++;
150             /*
151             The length of the remaining data should be equal to what was expected
152             Combined with the initial length check, there must be >= 8 bytes of pad
153             ftp://ftp.rsa.com/pub/pdfs/bulletn7.pdf
154             */
155 3354 50         if ((uint32) (end - c) != outlen)
156             {
157             psTraceCrypto("pkcs1Unpad verification failure\n");
158 0           return PS_LIMIT_FAIL;
159             }
160              
161             /* Copy the value bytes to the out buffer */
162 174405 100         while (c < end)
163             {
164 171051           *out = *c;
165 171051           out++; c++;
166             }
167 3354           return PS_SUCCESS;
168             }
169              
170             #ifdef USE_PRIVATE_KEY_PARSING
171              
172             # ifdef USE_PKCS8
173              
174 0           static int32 pkcs8parse_unknown(
175             psPool_t *pool,
176             unsigned char *buf,
177             int32 size,
178             psPubKey_t *key)
179             {
180             /* When PKCS #8 header appears correct, but format is not
181             RSA or ECDSA this function is called.
182             The function may be extended to parse public key formats usually
183             not processed by MatrixSSL. */
184              
185             psTraceCrypto("Unsupported public key type in PKCS#8 parse\n");
186 0           return PS_UNSUPPORTED_FAIL;
187             }
188              
189             /******************************************************************************/
190             /**
191             Parse PKCS#8 format keys (from DER formatted binary)
192              
193             'key' is dynamically allocated and must be freed with psFreePubKey() if
194             no error is returned from this API
195              
196             Unencrypted private keys are supported if 'pass' is NULL
197             Encrypted private keys are supported if 'pass' is non-null for the
198             des-EDE3-CBC algorithm only (3DES). Other PKCS#5 symmetric algorithms
199             are not supported.
200              
201             @return < 0 on error, private keysize in bytes on success.
202             */
203 142           int32 psPkcs8ParsePrivBin(psPool_t *pool, unsigned char *buf, int32 size,
204             char *pass, psPubKey_t *key)
205             {
206             const unsigned char *end, *p;
207             int32 version, oi;
208             psSize_t seqlen, len, plen;
209             # ifdef USE_ECC
210             int32 coi;
211             const psEccCurve_t *eccSet;
212             # endif
213             # ifdef USE_PKCS5
214             unsigned char desKeyBin[24];
215             psCipherContext_t ctx;
216             char iv[8], salt[8];
217             int32 icount;
218             # endif /* USE_PKCS5 */
219              
220             /* Check for too large (invalid) inputs, unparseable with uint16_t */
221 142 50         if (size > 65535)
222             {
223 0           return PS_FAILURE;
224             }
225              
226 142           p = buf;
227 142           end = p + size;
228              
229 142 100         if (pass)
230             {
231             psSize_t i;
232              
233             # ifdef USE_PKCS5
234             /* An encrypted PKCS#8 key has quite a bit more information we must parse
235             We actually parse a good bit of PKCS#5 structures here
236             */
237 4 100         if (getAsnSequence(&p, (int32) (end - p), &seqlen) < 0)
238             {
239 2           return PS_FAILURE;
240             }
241 2 50         if (getAsnAlgorithmIdentifier(&p, (int32) (end - p), &oi, &plen) < 0)
242             {
243             psTraceCrypto("Couldn't parse PKCS#8 algorithm identifier\n");
244 2           return PS_FAILURE;
245             }
246 0 0         if (oi != OID_PKCS_PBES2 || plen != 53)
    0          
247             {
248             psTraceCrypto("Only supporting PKCS#8 id-PBES2 OID\n");
249 0           return PS_FAILURE;
250             }
251 0 0         if (getAsnSequence(&p, (int32) (end - p), &seqlen) < 0)
252             {
253 0           return PS_FAILURE;
254             }
255 0 0         if (getAsnAlgorithmIdentifier(&p, (int32) (end - p), &oi, &plen) < 0)
256             {
257             psTraceCrypto("Couldn't parse PKCS#8 keyDerivationFunc\n");
258 0           return PS_FAILURE;
259             }
260 0 0         if (oi != OID_PKCS_PBKDF2 || plen != 16)
    0          
261             {
262             psTraceCrypto("Only support PKCS#8 id-PBKDF2 OID\n");
263 0           return PS_FAILURE;
264             }
265 0 0         if (getAsnSequence(&p, (int32) (end - p), &seqlen) < 0)
266             {
267 0           return PS_FAILURE;
268             }
269 0           if ((*p++ != ASN_OCTET_STRING) ||
270 0 0         getAsnLength(&p, (int32) (end - p), &len) < 0 ||
271 0 0         (uint32) (end - p) < len ||
272 0           len != 8)
273             {
274              
275             psTraceCrypto("Couldn't parse PKCS#8 param salt\n");
276 0           return PS_FAILURE;
277             }
278             /* Get the PBKDF2 Salt */
279 0           memcpy(salt, p, 8); p += 8;
280             /* Get the PBKDF2 Iteration count (rounds) */
281 0 0         if (getAsnInteger(&p, (int32) (end - p), &icount) < 0)
282             {
283             psTraceCrypto("Couldn't parse PKCS#8 param iterationCount\n");
284 0           return PS_FAILURE;
285             }
286             /* Get encryptionScheme */
287 0 0         if (getAsnAlgorithmIdentifier(&p, (int32) (end - p), &oi, &plen)
288             < 0)
289             {
290             psTraceCrypto("Couldn't parse PKCS#8 encryptionScheme\n");
291 0           return PS_FAILURE;
292             }
293 0 0         if (oi != OID_DES_EDE3_CBC || plen != 10)
    0          
294             {
295             psTraceCrypto("Only support des-EDE3-CBC OID\n");
296 0           return PS_FAILURE;
297             }
298 0 0         if ((uint32) (end - p) < 1)
299             {
300             psTraceCrypto("Couldn't parse PKCS#8 param CBC IV\n");
301 0           return PS_FAILURE;
302             }
303 0           if ((*p++ != ASN_OCTET_STRING) ||
304 0 0         getAsnLength(&p, (int32) (end - p), &len) < 0 ||
305 0 0         (uint32) (end - p) < len ||
306 0           len != DES3_IVLEN)
307             {
308              
309             psTraceCrypto("Couldn't parse PKCS#8 param CBC IV\n");
310 0           return PS_FAILURE;
311             }
312             /* Get the 3DES IV */
313 0           memcpy(iv, p, DES3_IVLEN); p += DES3_IVLEN;
314              
315             /* Now p points to the 3DES encrypted RSA key */
316 0 0         if ((uint32) (end - p) < 1)
317             {
318             psTraceCrypto("Couldn't parse PKCS#8 param CBC IV\n");
319 0           return PS_FAILURE;
320             }
321 0           if ((*p++ != ASN_OCTET_STRING) ||
322 0 0         getAsnLength(&p, (int32) (end - p), &len) < 0 ||
323 0 0         (uint32) (end - p) < len ||
324             # ifdef USE_ECC
325             /* May actually be an RSA key, but this check will be OK for now */
326 0           len < MIN_ECC_BITS / 8)
327             {
328             # else
329             len < MIN_RSA_BITS / 8) {
330             # endif
331              
332             psTraceCrypto("PKCS#8 decryption error\n");
333 0           return PS_FAILURE;
334             }
335             /* Derive the 3DES key and decrypt the RSA key*/
336 0           psPkcs5Pbkdf2((unsigned char *) pass, (int32) strlen(pass),
337             (unsigned char *) salt, 8, icount, (unsigned char *) desKeyBin,
338             DES3_KEYLEN);
339 0           psDes3Init(&ctx.des3, (unsigned char *) iv, desKeyBin);
340 0           psDes3Decrypt(&ctx.des3, p, (unsigned char *) p, len);
341             /* @security SECURITY - we zero out des3 key when done with it */
342 0           memset_s(&ctx, sizeof(psCipherContext_t), 0x0, sizeof(psCipherContext_t));
343 0           memset_s(desKeyBin, DES3_KEYLEN, 0x0, DES3_KEYLEN);
344              
345             /* Remove padding.
346             This implementation allows up-to 16 bytes padding, for
347             compatibility with 3DES and AES algorithms. */
348             /* Start by checking length. */
349             /* coverity[dead_error_condition] */
350             /* With the current value for MIN_ECC_BITS and MIN_RSA_BITS
351             this path can never be taken. This code path is ready in
352             case the values change in the future. */
353 0 0         if (len < 1)
354             {
355             /* coverity[dead_error_begin] */
356             psTraceCrypto("PKCS#8 padding error\n");
357 0           return PS_FAILURE;
358             }
359 0           plen = (unsigned char) p[len - 1];
360 0 0         if (plen < 1 || plen > 16)
    0          
361             {
362             psTraceCrypto("PKCS#8 padding error\n");
363 0           return PS_FAILURE;
364             }
365             /* coverity[dead_error_condition] */
366             /* With the current value for MIN_ECC_BITS and MIN_RSA_BITS
367             this path can never be taken. This code path is ready in
368             case the values change in the future. */
369 0 0         if (len < plen)
370             {
371             /* coverity[dead_error_begin] */
372             psTraceCrypto("PKCS#8 padding error\n");
373 0           return PS_FAILURE;
374             }
375 0 0         for(i = 0; i < plen; i++)
376             {
377 0 0         if (p[len - i - 1] != (unsigned char) plen)
378             {
379             psTraceCrypto("PKCS#8 padding error\n");
380 0           return PS_FAILURE;
381             }
382             }
383              
384             /* The padding has been processed. */
385 0           size = len - plen;
386 0           end = p + size;
387 0           buf = (unsigned char *)p;
388             # else /* !USE_PKCS5 */
389             /*
390             The private key is encrypted, but PKCS5 support has been turned off
391             */
392             psTraceCrypto("USE_PKCS5 must be enabled for key file password\n");
393             return PS_UNSUPPORTED_FAIL;
394             # endif /* USE_PKCS5 */
395             }
396              
397             /* PrivateKeyInfo per PKCS#8 Section 6. */
398 138 50         if (getAsnSequence(&p, (int32) (end - p), &seqlen) < 0)
399             {
400             psTraceCrypto("Initial PrivateKeyInfo parse failure\n");
401             # ifdef USE_PKCS5
402             if (pass)
403             {
404             psTraceCrypto("Is it possible the password is incorrect?\n");
405             }
406             # endif /* USE_PKCS5 */
407 0           return PS_FAILURE;
408             }
409             /* Version */
410 138 50         if (getAsnInteger(&p, (int32) (end - p), &version) < 0 || version != 0)
    50          
411             {
412             psTraceCrypto("Couldn't parse PKCS#8 algorithm identifier\n");
413 0           return PS_FAILURE;
414             }
415             /* privateKeyAlgorithmIdentifier */
416 138 50         if (getAsnAlgorithmIdentifier(&p, (int32) (end - p), &oi, &plen) < 0)
417             {
418             psTraceCrypto("Couldn't parse PKCS#8 algorithm identifier\n");
419 0           return PS_FAILURE;
420             }
421             # ifdef USE_ECC
422 138 50         if (oi != OID_ECDSA_KEY_ALG && oi != OID_RSA_KEY_ALG)
    50          
423             {
424 0           return pkcs8parse_unknown(pool, buf, size, key);
425             }
426 138 50         if (oi == OID_ECDSA_KEY_ALG)
427             {
428             /* Still a curve identifier sitting as param in the SEQUENCE */
429 0 0         if ((uint32) (end - p) < 1 || *p++ != ASN_OID)
    0          
430             {
431             psTraceCrypto("Expecting EC curve OID next\n");
432 0           return PS_PARSE_FAIL;
433             }
434 0 0         if (getAsnLength(&p, (uint32) (end - p), &len) < 0 ||
    0          
435 0           (uint32) (end - p) < len)
436             {
437             psTraceCrypto("Malformed extension length\n");
438 0           return PS_PARSE_FAIL;
439             }
440 0           coi = 0;
441 0 0         while (len > 0)
442             {
443 0           coi += *p; p++;
444 0           len--;
445             }
446 0 0         if (getEccParamByOid(coi, &eccSet) < 0)
447             {
448             psTraceCrypto("Unsupported EC curve OID\n");
449 0           return PS_UNSUPPORTED_FAIL;
450             }
451             }
452             # else
453             if (oi != OID_RSA_KEY_ALG || plen != 0)
454             {
455             return pkcs8parse_unknown(pool, buf, size, key);
456             }
457             # endif
458             /* PrivateKey Octet Stream */
459 138 50         if ((uint32) (end - p) < 1)
460             {
461             psTraceCrypto("Private Key len failure\n");
462 0           return PS_PARSE_FAIL;
463             }
464 276           if ((*p++ != ASN_OCTET_STRING) ||
465 276 50         getAsnLength(&p, (int32) (end - p), &len) < 0 ||
466 138           (uint32) (end - p) < len)
467             {
468             psTraceCrypto("getAsnLength parse error in psPkcs8ParsePrivBin\n");
469 0           return PS_FAILURE;
470             }
471             /* Note len can be zero here */
472             # ifdef USE_RSA
473 138 50         if (oi == OID_RSA_KEY_ALG)
474             {
475             /* Create the actual key here from the octet string */
476 138           psRsaInitKey(pool, &key->key.rsa);
477 138 50         if (psRsaParsePkcs1PrivKey(pool, p, len, &key->key.rsa) < 0)
478             {
479 0           psRsaClearKey(&key->key.rsa);
480 0           return PS_FAILURE;
481             }
482 138           key->type = PS_RSA;
483 138           key->keysize = psRsaSize(&key->key.rsa);
484             }
485             # endif
486             # ifdef USE_ECC
487 138 50         if (oi == OID_ECDSA_KEY_ALG)
488             {
489 0           psEccInitKey(pool, &key->key.ecc, eccSet);
490 0 0         if (psEccParsePrivKey(pool, p, len, &key->key.ecc, eccSet) < 0)
491             {
492 0           return PS_FAILURE;
493             }
494 0           key->type = PS_ECC;
495 0           key->keysize = psEccSize(&key->key.ecc);
496             }
497             # endif
498 138           p += len;
499              
500 138           plen = (int32) (end - p);
501 138 100         if (plen > 0)
502             {
503             /* attributes [0] Attributes OPTIONAL */
504 10 50         if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
505             {
506 0           p++;
507 0 0         if (getAsnLength(&p, (int32) (end - p), &len) < 0 ||
    0          
508 0           (uint32) (end - p) < len)
509             {
510              
511             psTraceCrypto("Error parsing pkcs#8 PrivateKey attributes\n");
512 0           return PS_FAILURE;
513             }
514             /* Ignore any attributes */
515 0           p += len;
516 0           plen = (int32) (end - p);
517             }
518              
519 10           if (plen > 0)
520             {
521             /* Unexpected extra data remains. Treat it as an error. */
522             psTraceIntCrypto("Unexpected extra data: %d\n", plen);
523             //goto PKCS8_FAIL;
524             }
525             }
526              
527 142           return PS_SUCCESS;
528              
529             PKCS8_FAIL:
530             psClearPubKey(key);
531             psTraceCrypto("Did not parse key in PKCS#8 parse\n");
532             return PS_FAILURE;
533             }
534              
535             # ifdef MATRIX_USE_FILE_SYSTEM
536             # ifdef USE_PKCS12
537             /******************************************************************************/
538             /*
539             A PKCS #7 ContentInfo, whose contentType is signedData in public-key
540             integrity mode and data in password integrity mode.
541              
542             Returns integrity mode or < 0 on failure
543             */
544             # define PASSWORD_INTEGRITY 1
545             # define PUBKEY_INTEGRITY 2
546 14           static int32 psParseIntegrityMode(const unsigned char **buf, int32 totLen)
547             {
548             const unsigned char *p, *end;
549             psSize_t totcontentlen, len, oiLen;
550             int32 rc, oi;
551              
552 14           p = *buf;
553 14           end = p + totLen;
554              
555 14 50         if ((rc = getAsnAlgorithmIdentifier(&p, totLen, &oi, &oiLen)) < 0)
556             {
557             psTraceCrypto("Initial integrity parse error\n");
558 0           return rc;
559             }
560              
561 14 50         if (oi == OID_PKCS7_DATA)
562             {
563             /* Data ::= OCTET STRING */
564 14 50         if (*p++ != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
565             {
566 0           return PS_PARSE_FAIL;
567             }
568 14 50         if ((rc = getAsnLength(&p, (int32) (end - p), &len)) < 0)
569             {
570 0           return PS_PARSE_FAIL;
571             }
572 28           if ((*p++ != ASN_OCTET_STRING) ||
573 14           getAsnLength(&p, (int32) (end - p), &totcontentlen) < 0)
574             {
575             psTraceCrypto("Couldn't parse data from ContentInfo\n");
576 0           return PS_FAILURE;
577             }
578 14           rc = PASSWORD_INTEGRITY;
579             }
580 0 0         else if (oi == OID_PKCS7_SIGNED_DATA)
581             {
582             psTraceCrypto("SignedData integrity mode not supported\n");
583 0           return PS_UNSUPPORTED_FAIL;
584             /* rc = PUBKEY_INTEGRITY; */
585             }
586             else
587             {
588             psTraceCrypto("Unknown integrity mode\n");
589 0           return PS_UNSUPPORTED_FAIL;
590             }
591              
592 14           *buf = (unsigned char *) p;
593 14           return rc;
594             }
595              
596             /******************************************************************************/
597             /*
598             Generate a key given a password, salt and iteration value.
599              
600             B.2 General method from PKCS#12
601              
602             Assumptions: hash is SHA-1, password is < 128 bytes
603             */
604 58           static int32 pkcs12pbe(psPool_t *pool, unsigned char *password, uint32 passLen,
605             unsigned char *salt, int saltLen, int32 iter, int32 id,
606             unsigned char **out, uint32 *outlen)
607             {
608             psSha1_t ctx;
609             pstm_int bigb, bigone, bigtmp;
610             unsigned char diversifier[64], saltpass[192], hash[SHA1_HASH_SIZE];
611             unsigned char B[65];
612             unsigned char *p, *front;
613             int32 i, j, copy, count, cpyLen, binsize, plen;
614              
615 58           *out = NULL;
616 58           memset(diversifier, id, 64);
617              
618 522 100         for (i = 0; i < 64; )
619             {
620 464 50         if ((64 - i) < saltLen)
621             {
622 0           memcpy(&saltpass[i], salt, 64 - i);
623 0           i = 64;
624             }
625             else
626             {
627 464           memcpy(&saltpass[i], salt, saltLen);
628 464           i += saltLen;
629             }
630             }
631              
632 58           plen = 64 * ((passLen + 64 - 1) / 64);
633 58 50         if (plen + 64 > 192)
634             {
635 0           return PS_UNSUPPORTED_FAIL;
636             }
637 3770 100         for (i = 0; i < plen; i++)
638             {
639 3712           saltpass[64 + i] = password[i % passLen];
640             }
641              
642 58 100         if (*outlen == SHA1_HASH_SIZE)
643             {
644 10           count = 1;
645             }
646             else
647             {
648 48           count = (*outlen / SHA1_HASH_SIZE) + 1;
649             }
650 58           cpyLen = *outlen;
651              
652 58           front = p = psMalloc(pool, cpyLen);
653 58 50         if (front == NULL)
654             {
655 0           return PS_MEM_FAIL;
656             }
657              
658 126 100         while (count)
659             {
660 68           psSha1Init(&ctx);
661 68           psSha1Update(&ctx, diversifier, 64);
662 68           psSha1Update(&ctx, saltpass, 64 + plen);
663 68           psSha1Final(&ctx, hash);
664 139264 100         for (j = 1; j < iter; j++)
665             {
666 139196           psSha1Init(&ctx);
667 139196           psSha1Update(&ctx, hash, SHA1_HASH_SIZE);
668 139196           psSha1Final(&ctx, hash);
669             }
670             /* Copy into outgoing key now */
671 68           copy = min(cpyLen, SHA1_HASH_SIZE);
672 68           memcpy(p, hash, copy);
673 68           p += copy;
674 68           count--;
675 68           cpyLen -= copy;
676              
677 68 100         if (cpyLen > 0)
678             {
679             /* manipulate saltpass */
680 650 100         for (j = 0; j < 64; j++)
681             {
682 640           B[j] = hash[j % SHA1_HASH_SIZE];
683             }
684 10 50         if (pstm_init_for_read_unsigned_bin(pool, &bigb, 64) < 0)
685             {
686 0           psFree(front, pool);
687 0           return PS_MEM_FAIL;
688             }
689 10 50         if (pstm_read_unsigned_bin(&bigb, B, 64) < 0)
690             {
691 0           pstm_clear(&bigb);
692 0           psFree(front, pool);
693 0           return PS_MEM_FAIL;
694             }
695 10 50         if (pstm_init_for_read_unsigned_bin(pool, &bigone, 1) < 0)
696             {
697 0           pstm_clear(&bigb);
698 0           psFree(front, pool);
699 0           return PS_MEM_FAIL;
700             }
701 10           pstm_set(&bigone, 1);
702 10 50         if (pstm_add(&bigb, &bigone, &bigb) < 0)
703             {
704 0           pstm_clear(&bigone);
705 0           pstm_clear(&bigb);
706 0           psFree(front, pool);
707 0           return PS_MEM_FAIL;
708             }
709 10           pstm_clear(&bigone);
710 30 100         for (j = 0; j < 64 + plen; j += 64)
711             {
712 20 50         if (pstm_init_for_read_unsigned_bin(pool, &bigtmp, 64) < 0)
713             {
714 0           pstm_clear(&bigone);
715 0           pstm_clear(&bigb);
716 0           psFree(front, pool);
717 0           return PS_MEM_FAIL;
718             }
719 20 50         if (pstm_read_unsigned_bin(&bigtmp, saltpass + j, 64) < 0)
720             {
721 0           pstm_clear(&bigone);
722 0           pstm_clear(&bigb);
723 0           pstm_clear(&bigtmp);
724 0           psFree(front, pool);
725 0           return PS_MEM_FAIL;
726             }
727 20 50         if (pstm_add(&bigb, &bigtmp, &bigtmp) < 0)
728             {
729 0           pstm_clear(&bigone);
730 0           pstm_clear(&bigb);
731 0           pstm_clear(&bigtmp);
732 0           psFree(front, pool);
733 0           return PS_MEM_FAIL;
734             }
735 20           binsize = pstm_unsigned_bin_size(&bigtmp);
736 20 100         if (binsize > 64)
737             {
738 1 50         psAssert(binsize == 65);
739 1 50         if (pstm_to_unsigned_bin(pool, &bigtmp, B) < 0)
740             {
741 0           pstm_clear(&bigone);
742 0           pstm_clear(&bigb);
743 0           pstm_clear(&bigtmp);
744 0           psFree(front, pool);
745 0           return PS_MEM_FAIL;
746             }
747 1           memcpy(saltpass + j, B + 1, 64); /* truncate */
748             }
749 19 50         else if (binsize < 64)
750             {
751 0 0         psAssert(binsize == 63);
752 0           memset(saltpass + j, 0x0, 1); /* pad with a zero */
753 0 0         if (pstm_to_unsigned_bin(pool, &bigtmp, saltpass + j + 1) < 0)
754             {
755 0           pstm_clear(&bigone);
756 0           pstm_clear(&bigb);
757 0           pstm_clear(&bigtmp);
758 0           psFree(front, pool);
759 0           return PS_MEM_FAIL;
760             }
761             }
762             else
763             {
764 19 50         if (pstm_to_unsigned_bin(pool, &bigtmp, saltpass + j) < 0)
765             {
766 0           pstm_clear(&bigone);
767 0           pstm_clear(&bigb);
768 0           pstm_clear(&bigtmp);
769 0           psFree(front, pool);
770 0           return PS_MEM_FAIL;
771             }
772             }
773 20           pstm_clear(&bigtmp);
774             }
775 10           pstm_clear(&bigone);
776 10           pstm_clear(&bigb);
777             }
778             }
779              
780 58           *out = front;
781 58           return PS_SUCCESS;
782             }
783              
784             /******************************************************************************/
785             /*
786             Return value is how many bytes were parsed out of buf
787             */
788 24           static int32 pkcs12import(psPool_t *pool, const unsigned char **buf,
789             psSize_t bufLen, unsigned char *password, psSize_t passLen,
790             unsigned char **plaintext, psSize_t *ptLen)
791             {
792             psCipherContext_t ctx;
793             const unsigned char *p, *start, *end;
794             unsigned char *iv, *decryptKey, *pt;
795             unsigned char salt[8];
796             int32 rc, oi, asnint;
797             uint32_t keyLen, ivLen;
798             psSize_t tmplen, tmpint;
799             short cipher;
800 24           const short armor = PBE12;
801              
802 24           *plaintext = NULL;
803 24           *ptLen = 0;
804 24           decryptKey = NULL;
805              
806 24           p = start = *buf;
807 24           end = p + bufLen;
808              
809             /* Encryption Algorithm */
810 24 50         if ((rc = getAsnAlgorithmIdentifier(&p, (int32) (end - p), &oi,
811             &tmpint)) < 0)
812             {
813             psTraceCrypto("Initial pkcs12import parse failure\n");
814 0           return rc;
815             }
816              
817 24 100         if (oi == OID_PKCS_PBESHA40RC2)
818             {
819             # ifdef USE_RC2
820 14           cipher = AUTH_SAFE_RC2;
821 14           keyLen = 8;
822             # else
823             psTraceCrypto("Must enable USE_RC2 in cryptoConfig.h to parse\n");
824             return PS_UNSUPPORTED_FAIL;
825             # endif
826             }
827 10 50         else if (oi == OID_PKCS_PBESHA3DES3)
828             {
829 10           cipher = AUTH_SAFE_3DES;
830 10           keyLen = DES3_KEYLEN;
831             }
832             else
833             {
834             psTraceIntCrypto("Unsupported PBE algorithm %d\n", oi);
835 0           return PS_UNSUPPORTED_FAIL;
836             }
837              
838 24 50         if (armor == PBE12)
839             {
840             /* If PKCS12 param will be
841             pkcs-12PbeParams ::= SEQUENCE {
842             salt OCTET STRING,
843             iterations INTEGER
844             }
845             */
846 24 50         if ((rc = getAsnSequence(&p, (int32) (end - p), &tmplen)) < 0)
847             {
848             psTraceCrypto("Initial PBE12 parse failure\n");
849 0           return rc;
850             }
851             /* salt len */
852 48 50         if ((uint32) (end - p) < 1 || (*p++ != ASN_OCTET_STRING) ||
853 48 50         getAsnLength(&p, (int32) (end - p), &tmplen) < 0 ||
854 24 50         (uint32) (end - p) < tmplen ||
855 24           tmplen != 8)
856             {
857              
858             psTraceCrypto("Bad salt length parsing import\n");
859 0           return PS_PARSE_FAIL;
860             }
861 24           memcpy(salt, p, tmplen);
862 24           p += tmplen;
863             /* iteration count */
864 24 50         if (getAsnInteger(&p, (int32) (end - p), &asnint) < 0)
865             {
866 0           return PS_PARSE_FAIL;
867             }
868 24 50         if (pkcs12pbe(pool, password, passLen, salt, 8, asnint,
869             PKCS12_KEY_ID, &decryptKey, &keyLen) < 0)
870             {
871             psTraceCrypto("Error generating pkcs12 key\n");
872 0           return PS_UNSUPPORTED_FAIL;
873             }
874 24           ivLen = 8;
875 24 50         if (pkcs12pbe(pool, password, passLen, salt, 8, asnint,
876             PKCS12_IV_ID, &iv, &ivLen) < 0)
877             {
878             psTraceCrypto("Error generating pkcs12 iv\n");
879 0 0         if (decryptKey)
880             {
881 0           memset_s(decryptKey, keyLen, 0x0, keyLen);
882 0           psFree(decryptKey, pool);
883             }
884 0           return PS_UNSUPPORTED_FAIL;
885             }
886             }
887              
888             /* Got the keys but we still need to find the start of the encrypted data.
889             Have seen a few different BER variations at this point in the spec
890             depending on what wrapper we are in. Try all that we know about
891             */
892 24 50         if ((uint32) (end - p) < 1)
893             {
894 0           return PS_PARSE_FAIL;
895             }
896 24 100         if (*p == (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE))
897             {
898 14           p++;
899 14 50         if ((rc = getAsnLength(&p, (int32) (end - p), &tmplen)) < 0)
900             {
901 0 0         if (decryptKey)
902             {
903 0           memset_s(decryptKey, keyLen, 0x0, keyLen);
904 0           psFree(decryptKey, pool);
905             }
906 0           psFree(iv, pool);
907 0           return PS_PARSE_FAIL;
908             }
909             }
910 10 50         else if (*p == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
911             {
912 0           p++;
913 0 0         if ((rc = getAsnLength(&p, (int32) (end - p), &tmplen)) < 0)
914             {
915 0 0         if (decryptKey)
916             {
917 0           memset_s(decryptKey, keyLen, 0x0, keyLen);
918 0           psFree(decryptKey, pool);
919             }
920 0           psFree(iv, pool);
921 0           return PS_PARSE_FAIL;
922             }
923 0 0         if ((uint32) (end - p) < 1 ||
    0          
924 0 0         *p++ != ASN_OCTET_STRING ||
925 0           getAsnLength(&p, (int32) (end - p), &tmplen) < 0)
926             {
927 0 0         if (decryptKey)
928             {
929 0           memset_s(decryptKey, keyLen, 0x0, keyLen);
930 0           psFree(decryptKey, pool);
931             }
932 0           psFree(iv, pool);
933 0           return PS_PARSE_FAIL;
934             }
935             }
936 10 50         else if (*p == ASN_OCTET_STRING)
937             {
938 10           p++;
939 10 50         if ((rc = getAsnLength(&p, (int32) (end - p), &tmplen)) < 0)
940             {
941 0 0         if (decryptKey)
942             {
943 0           memset_s(decryptKey, keyLen, 0x0, keyLen);
944 0           psFree(decryptKey, pool);
945             }
946 0           psFree(iv, pool);
947 0           return PS_PARSE_FAIL;
948             }
949             }
950             else
951             {
952             psTraceCrypto("Error finding ciphertext in pkcs12import\n");
953 0 0         if (decryptKey)
954             {
955 0           memset_s(decryptKey, keyLen, 0x0, keyLen);
956 0           psFree(decryptKey, pool);
957             }
958 0           psFree(iv, pool);
959 0           return PS_PARSE_FAIL;
960             }
961              
962 24 50         if (tmplen < 1 || (uint32) (end - p) < tmplen)
    50          
963             {
964 0           return PS_PARSE_FAIL;
965             }
966              
967             /* Don't decrypt in-situ because we'll need to MAC this all later */
968 24 50         if ((pt = psMalloc(pool, tmplen)) == NULL)
969             {
970             psTraceCrypto("Out-of-memory. Increase SSL_KEY_POOL_SIZE\n");
971 0 0         if (decryptKey)
972             {
973 0           memset_s(decryptKey, keyLen, 0x0, keyLen);
974 0           psFree(decryptKey, pool);
975             }
976 0           psFree(iv, pool);
977 0           return PS_MEM_FAIL;
978             }
979 24 100         if (cipher == AUTH_SAFE_3DES)
980             {
981 10 50         if ((rc = psDes3Init(&ctx.des3, iv, decryptKey)) < 0)
982             {
983 0           memset_s(&ctx, sizeof(psCipherContext_t), 0x0, sizeof(psCipherContext_t));
984 0 0         if (decryptKey)
985             {
986 0           memset_s(decryptKey, keyLen, 0x0, keyLen);
987 0           psFree(decryptKey, pool);
988             }
989 0           psFree(iv, pool);
990 0           psFree(pt, pool);
991 0           return rc;
992             }
993 10           psDes3Decrypt(&ctx.des3, p, pt, tmplen);
994             }
995             # ifdef USE_RC2
996 24 100         if (cipher == AUTH_SAFE_RC2)
997             {
998              
999             /* This is a 40-bit RC2! */
1000 14 50         if ((rc = psRc2Init(&ctx.rc2, iv, decryptKey, 5)) < 0)
1001             {
1002 0           memset_s(&ctx, sizeof(psCipherContext_t), 0x0, sizeof(psCipherContext_t));
1003 0 0         if (decryptKey)
1004             {
1005 0           memset_s(decryptKey, keyLen, 0x0, keyLen);
1006 0           psFree(decryptKey, pool);
1007             }
1008 0           psFree(iv, pool);
1009 0           psFree(pt, pool);
1010 0           return rc;
1011             }
1012 14 50         if ((rc = psRc2Decrypt(&ctx.rc2, p, pt, tmplen)) < 0)
1013             {
1014 0           memset_s(&ctx, sizeof(psCipherContext_t), 0x0, sizeof(psCipherContext_t));
1015 0 0         if (decryptKey)
1016             {
1017 0           memset_s(decryptKey, keyLen, 0x0, keyLen);
1018 0           psFree(decryptKey, pool);
1019             }
1020 0           psFree(iv, pool);
1021 0           psFree(pt, pool);
1022 0           return rc;
1023             }
1024             }
1025             # endif /* USE_RC2 */
1026              
1027 24 50         if (decryptKey)
1028             {
1029 24           memset_s(decryptKey, keyLen, 0x0, keyLen);
1030 24           psFree(decryptKey, pool);
1031             }
1032 24           psFree(iv, pool);
1033              
1034 24           *plaintext = pt;
1035 24           *ptLen = tmplen;
1036 24           return (int32) (p - start);
1037             }
1038              
1039             /******************************************************************************/
1040             /*
1041             Determines what the safebag is and loads the material into the users
1042             data structure (cert or private key)
1043             */
1044 24           static int32 parseSafeContents(psPool_t *pool, unsigned char *password,
1045             uint32 passLen, psX509Cert_t **cert, psPubKey_t *privKey,
1046             unsigned char *buf, uint32 totlen)
1047             {
1048             psX509Cert_t *currCert, *frontCert;
1049             const unsigned char *p, *end;
1050             unsigned char *pt, *safeLen;
1051             psSize_t tmplen, cryptlen, tmpint;
1052             int32 rc, bagoi, certoi;
1053              
1054             # ifdef PARSE_PKCS12_SAFE_ATTRIBS
1055             uint32 attriblen;
1056             int32 attriboi;
1057             # endif
1058              
1059 24           p = buf;
1060 24           end = p + totlen;
1061              
1062             /* SafeContents ::= SEQUENCE OF SafeBag
1063              
1064             SafeBag ::= SEQUENCE {
1065             bagId BAG-TYPE.&id ({PKCS12BagSet})
1066             bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}),
1067             bagAttributes SET OF PKCS12Attribute OPTIONAL
1068             } */
1069 24 100         if ((rc = getAsnSequence(&p, (int32) (end - p), &tmplen)) < 0)
1070             {
1071             psTraceCrypto("Initial SafeContents parse failure\n");
1072 4           return rc;
1073             }
1074              
1075 20           end = p + tmplen;
1076              
1077 41 100         while (p < end)
1078             {
1079             /*
1080             bagtypes OBJECT IDENTIFIER ::= {pkcs-12 10 1}
1081              
1082             BAG-TYPE ::= TYPE-IDENTIFIER
1083             keyBag BAG-TYPE ::= {KeyBag IDENTIFIED BY {bagtypes 1}}
1084             pkcs8ShroudedKeyBag BAG-TYPE ::= {PKCS8ShroudedKeyBag IDENTIFIED BY
1085             {bagtypes 2}}
1086             certBag BAG-TYPE ::= {CertBag IDENTIFIED BY {bagtypes 3}}
1087             crlBag BAG-TYPE ::= {CRLBag IDENTIFIED BY {bagtypes 4}}
1088             secretBag BAG-TYPE ::= {SecretBag IDENTIFIED BY {bagtypes 5}}
1089             safeContentsBag BAG-TYPE ::= {SafeContents IDENTIFIED BY
1090             {bagtypes 6}}
1091              
1092             PKCS12BagSet BAG-TYPE ::= {
1093             keyBag | pkcs8ShroudedKeyBag | certBag | crlBag | secretBag |
1094             safeContentsBag, ... -- For future extensions}
1095              
1096             */
1097 21 50         if ((rc = getAsnAlgorithmIdentifier(&p, (int32) (end - p), &bagoi,
1098             &tmpint)) < 0)
1099             {
1100             psTraceCrypto("Initial BagType parse failure\n");
1101 0           return rc;
1102             }
1103 21           safeLen = (unsigned char *) p + tmpint;
1104 21 50         if (*p++ != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
1105             {
1106 0           return PS_PARSE_FAIL;
1107             }
1108 21 50         if ((rc = getAsnLength(&p, (int32) (end - p), &tmplen)) < 0)
1109             {
1110 0           return PS_PARSE_FAIL;
1111             }
1112              
1113 21           switch (bagoi)
1114             {
1115             case OID_PKCS12_BAG_TYPE_CERT:
1116             /*
1117             CertBag ::= SEQUENCE {
1118             certId BAG-TYPE.&id ({CertTypes}),
1119             certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) }
1120              
1121             x509Certificate BAG-TYPE ::=
1122             {OCTET STRING IDENTIFIED BY {certTypes 1}}
1123             -- DER-encoded X.509 certificate stored in OCTET STRING
1124             sdsiCertificate BAG-TYPE ::=
1125             {IA5String IDENTIFIED BY {certTypes 2}}
1126             -- Base64-encoded SDSI certificate stored in IA5String
1127              
1128             CertTypes BAG-TYPE ::= {
1129             x509Certificate |
1130             sdsiCertificate,
1131             ... -- For future extensions
1132             }
1133             */
1134 11 50         if ((rc = getAsnAlgorithmIdentifier(&p, (int32) (end - p),
1135             &certoi, &tmpint)) < 0)
1136             {
1137             psTraceCrypto("Initial CertBag parse failure\n");
1138 0           return rc;
1139             }
1140 11 50         if (certoi != OID_PKCS9_CERT_TYPE_X509)
1141             {
1142             psTraceIntCrypto("Unsupported CertBag type %d\n", certoi);
1143 0           return PS_UNSUPPORTED_FAIL;
1144             }
1145 11 50         if (*p++ != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
1146             {
1147 0           return PS_PARSE_FAIL;
1148             }
1149 11 50         if ((rc = getAsnLength(&p, (int32) (end - p), &tmplen)) < 0)
1150             {
1151 0           return rc;
1152             }
1153 22           if ((*p++ != ASN_OCTET_STRING) ||
1154 11           getAsnLength(&p, (int32) (end - p), &tmplen) < 0)
1155             {
1156             psTraceCrypto("Couldn't extract X509 CertBag\n");
1157 0           return PS_FAILURE;
1158             }
1159             /* Support cert chains */
1160 11           currCert = frontCert = *cert;
1161 12 100         while (currCert != NULL)
1162             {
1163 1           currCert = currCert->next;
1164             }
1165 11 50         if ((rc = psX509ParseCert(pool, p, tmplen, &currCert,
1166             CERT_STORE_UNPARSED_BUFFER)) < 0)
1167             {
1168 0           psX509FreeCert(currCert);
1169 0           *cert = NULL;
1170             psTraceCrypto("Couldn't parse certificate from CertBag\n");
1171 0           return rc;
1172             }
1173 11 100         if (*cert == NULL)
1174             {
1175 10           *cert = currCert;
1176             }
1177             else
1178             {
1179 1 50         while (frontCert->next != NULL)
1180             {
1181 0           frontCert = frontCert->next;
1182             }
1183 1           frontCert->next = currCert;
1184             }
1185 11           p += rc;
1186 11           break;
1187              
1188             case OID_PKCS12_BAG_TYPE_SHROUD:
1189             /* A PKCS8ShroudedKeyBag holds a private key, which has been
1190             shrouded in accordance with PKCS #8. Note that a
1191             PKCS8ShroudedKeyBag holds only one shrouded private key. */
1192 10 50         if (getAsnSequence(&p, (int32) (end - p), &tmplen) < 0)
1193             {
1194             psTraceCrypto("Initial PKCS8 ShroudKeyBag parse failure\n");
1195 0           return PS_PARSE_FAIL;
1196             }
1197 10 50         if ((rc = pkcs12import(pool, &p,
1198 10           (int32) (end - p), password, passLen, &pt, &cryptlen)) < 0)
1199             {
1200             psTraceIntCrypto("Import failed from AuthSafe %d\n", rc);
1201 0           return rc;
1202             }
1203 10           p += rc;
1204             /* Result of decrypt will be a PKCS#8 key */
1205 10 50         if ((rc = psPkcs8ParsePrivBin(pool, pt, cryptlen, NULL, privKey))
1206             < 0)
1207             {
1208 0           psFree(pt, pool);
1209             psTraceIntCrypto("Failed shroud PKCS8 key parse %d\n", rc);
1210 0           return rc;
1211             }
1212 10           psFree(pt, pool);
1213 10           p += cryptlen;
1214 10           break;
1215             case OID_PKCS12_BAG_TYPE_KEY:
1216 0 0         if ((rc = psPkcs8ParsePrivBin(pool, (unsigned char *) p, tmplen,
1217             NULL, privKey)) < 0)
1218             {
1219             psTraceIntCrypto("Failed PKCS8 key parse %d\n", rc);
1220 0           return rc;
1221             }
1222 0           p += tmplen;
1223 0           break;
1224             default:
1225             psTraceIntCrypto("Unsupported BAG_TYPE %d\n", bagoi);
1226 0           return PS_UNSUPPORTED_FAIL;
1227             }
1228              
1229             /* Attributes are at the end of the data */
1230 41 100         while (p != safeLen)
1231             {
1232             # ifdef PARSE_PKCS12_SAFE_ATTRIBS
1233             /**/
1234             if ((rc = getAsnSet(&p, (int32) (end - p), &attriblen)) < 0)
1235             {
1236             return rc;
1237             }
1238             if ((rc = getAsnAlgorithmIdentifier(&p, (int32) (end - p), &attriboi,
1239             &pLen)) < 0)
1240             {
1241             return rc;
1242             }
1243             if ((rc = getAsnSet(&p, (int32) (end - p), &attriblen)) < 0)
1244             {
1245             return rc;
1246             }
1247             if ((*p++ != ASN_OCTET_STRING) ||
1248             getAsnLength(&p, (int32) (end - p), &tmplen) < 0)
1249             {
1250             psTraceCrypto("Couldn't parse PKCS#8 param salt\n");
1251             return PS_FAILURE;
1252             }
1253             p += tmplen;
1254             # else
1255 20           p = safeLen;
1256             # endif
1257             }
1258             }
1259 24           return totlen;
1260             }
1261              
1262             /******************************************************************************/
1263             /*
1264             AuthenticatedSafe ::= SEQUENCE OF ContentInfo
1265             -- Data if unencrypted
1266             -- EncryptedData if password-encrypted
1267             -- EnvelopedData if public key-encrypted
1268             */
1269 14           static int32 psParseAuthenticatedSafe(psPool_t *pool, psX509Cert_t **cert,
1270             psPubKey_t *privKey, unsigned char *importPass, int32 ipassLen,
1271             unsigned char **buf, int32 totLen)
1272             {
1273             const unsigned char *p, *end;
1274             unsigned char *pt;
1275             psSize_t tmplen, tmpint;
1276             int32_t asnint;
1277             int32 rc, oi;
1278              
1279 14           p = *buf;
1280 14           end = p + totLen;
1281 14 50         if ((rc = getAsnSequence(&p, (int32) (end - p), &tmplen)) < 0)
1282             {
1283             psTraceCrypto("Initial authenticated safe parse failure\n");
1284 0           return rc;
1285             }
1286              
1287 14           end = p + tmplen; /* Set end to be end of authSafe for list walk */
1288              
1289 34 100         while (p < end)
1290             {
1291 24 50         if ((rc = getAsnAlgorithmIdentifier(&p, (int32) (end - p), &oi,
1292             &tmpint)) < 0)
1293             {
1294             psTraceCrypto("Initial content info parse failure\n");
1295 0           return rc;
1296             }
1297 24 100         if (oi == OID_PKCS7_ENCRYPTED_DATA)
1298             {
1299             /* password protected mode */
1300 14 50         if (*p++ != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
1301             {
1302             psTraceCrypto("Initial pkcs7 encrypted data parse failure\n");
1303 0           return PS_PARSE_FAIL;
1304             }
1305 14 50         if ((rc = getAsnLength(&p, (int32) (end - p), &tmplen)) < 0)
1306             {
1307 0           return PS_PARSE_FAIL;
1308             }
1309             /* EncryptedData ::= SEQUENCE {
1310             version Version,
1311             encryptedContentInfo EncryptedContentInfo } */
1312 14 50         if ((rc = getAsnSequence(&p, (int32) (end - p), &tmplen)) < 0)
1313             {
1314 0           return rc;
1315             }
1316             /* Version */
1317 14 50         if (getAsnInteger(&p, (int32) (end - p), &asnint) < 0 ||
    50          
1318 14           asnint != 0)
1319             {
1320             psTraceIntCrypto("Unsupported encryptd data version %d\n",
1321             asnint);
1322 0           return PS_UNSUPPORTED_FAIL;
1323             }
1324             /*
1325             EncryptedContentInfo ::= SEQUENCE {
1326             contentType ContentType,
1327             contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
1328             encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
1329              
1330             5.1 2b) If SCi is to be encrypted with a password, make a
1331             ContentInfo CIi of type EncryptedData. The encryptedContentInfo
1332             field of CIi has its contentType field set to data and its
1333             encryptedContent field set to the encryption of the BER-encoding
1334             of SCi (note that the tag and length octets shall be present). */
1335 14 50         if ((rc = getAsnAlgorithmIdentifier(&p, (int32) (end - p), &oi,
1336             &tmpint)) < 0)
1337             {
1338             psTraceCrypto("Initial EncryptedContentInfo parse failure\n");
1339 0           return rc;
1340             }
1341 14 50         psAssert(oi == OID_PKCS7_DATA);
1342              
1343 14 50         if ((rc = pkcs12import(pool, &p, (int32) (end - p), importPass,
1344             ipassLen, &pt, &tmplen)) < 0)
1345             {
1346             psTraceIntCrypto("Import failed from AuthSafe %d\n", rc);
1347 0           return rc;
1348             }
1349 14           p += rc;
1350              
1351             /* pt is now a BER-encoded SafeContents */
1352 14 100         if ((rc = parseSafeContents(pool, importPass, ipassLen, cert,
1353             privKey, pt, tmplen)) < 0)
1354             {
1355             psTraceCrypto("Error parsing encrypted safe contents\n");
1356             psTraceCrypto("Is it possible the password is incorrect?\n");
1357 4           psFree(pt, pool);
1358 4           return rc;
1359             }
1360 10           psFree(pt, pool);
1361 10           p += rc;
1362             }
1363 10 50         else if (oi == OID_PKCS7_DATA)
1364             {
1365             /* Data ::= OCTET STRING */
1366 10 50         if (*p++ != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
1367             {
1368             psTraceCrypto("Initial pkcs7 data parse failure\n");
1369 0           return PS_PARSE_FAIL;
1370             }
1371 10 50         if ((rc = getAsnLength(&p, (int32) (end - p), &tmplen)) < 0)
1372             {
1373 0           return PS_PARSE_FAIL;
1374             }
1375 10 50         if (*p++ != ASN_OCTET_STRING || getAsnLength(&p,
    50          
1376 10           (int32) (end - p), &tmplen) < 0)
1377             {
1378 0           return PS_PARSE_FAIL;
1379             }
1380 10 50         if ((rc = parseSafeContents(pool, importPass, ipassLen, cert,
1381             privKey, (unsigned char *) p, tmplen)) < 0)
1382             {
1383             psTraceCrypto("Error parsing plaintext safe contents\n");
1384 0           return rc;
1385             }
1386 10           p += rc;
1387             }
1388             else
1389             {
1390             psTraceIntCrypto("Unsupported PKCS7 data type parse %d\n", oi);
1391 0           return PS_UNSUPPORTED_FAIL;
1392             }
1393             }
1394              
1395 10           *buf = (unsigned char *) p;
1396 14           return PS_SUCCESS;
1397             }
1398              
1399             /******************************************************************************/
1400             /*
1401              
1402             MacData ::= SEQUENCE {
1403             mac DigestInfo,
1404             macSalt OCTET STRING,
1405             iterations INTEGER DEFAULT 1
1406             }
1407             */
1408 15           int32 psPkcs12Parse(psPool_t *pool, psX509Cert_t **cert, psPubKey_t *privKey,
1409             const unsigned char *file, int32 flags, unsigned char *password,
1410             int32 pLen, unsigned char *macPass, int32 macPassLen)
1411             {
1412             psHmacSha1_t hmac;
1413             const unsigned char *p, *end, *macStart, *macEnd;
1414             unsigned char *fileBuf, *macKey;
1415             unsigned char iwidePass[128]; /* 63 char password max */
1416             unsigned char mwidePass[128];
1417             unsigned char mac[SHA1_HASH_SIZE];
1418             unsigned char macSalt[20];
1419             unsigned char digest[SHA1_HASH_SIZE];
1420             psSize_t tmplen, tmpint;
1421             uint32 digestLen, macKeyLen;
1422             int32 fsize, i, j, rc, mpassLen, ipassLen, integrity, oi, asnint;
1423              
1424 15           *cert = NULL;
1425 15 100         if ((rc = psGetFileBuf(pool, (char *) file, &fileBuf, &fsize)) < PS_SUCCESS)
1426             {
1427             psTraceStrCrypto("Couldn't open PKCS#12 file %s\n", (char *) file);
1428 1           return rc;
1429             }
1430 14           p = fileBuf;
1431 14           end = p + fsize;
1432              
1433             /* Begin with a PFX
1434             PFX ::= SEQUENCE {
1435             version INTEGER {v3(3)}(v3,...),
1436             authSafe ContentInfo,
1437             macData MacData OPTIONAL } */
1438 14 50         if ((rc = getAsnSequence(&p, (int32) (end - p), &tmplen)) < 0)
1439             {
1440             psTraceCrypto("Initial PKCS#12 parse fail\n");
1441 0           goto ERR_FBUF;
1442             }
1443             /* Version */
1444 14 50         if (getAsnInteger(&p, (int32) (end - p), &asnint) < 0 || asnint != 3)
    50          
1445             {
1446             psTraceIntCrypto("Unsupported PKCS#12 version %d\n", asnint);
1447 0           rc = PS_UNSUPPORTED_FAIL;
1448 0           goto ERR_FBUF;
1449             }
1450              
1451             /* Content type is the integrity mode (4 of the spec).
1452             signedData for public-key integrity or data for password integrity */
1453 14 50         if ((integrity = psParseIntegrityMode(&p, (int32) (end - p)))
1454             < PS_SUCCESS)
1455             {
1456             psTraceCrypto("Couldn't determine PKCS#12 integrity\n");
1457 0           rc = integrity;
1458 0           goto ERR_FBUF;
1459             }
1460              
1461             /* Passwords are wide BMPString types
1462             ipass is import password
1463             mpass is MAC password */
1464 14           ipassLen = (pLen * 2) + 2; /* 2 for each char put double 0x0 to terminate */
1465 14           memset(iwidePass, 0x0, ipassLen);
1466 48 100         for (i = 1, j = 0; i < ipassLen - 1; i += 2, j++)
1467             {
1468 34           iwidePass[i] = password[j];
1469             }
1470              
1471             /* Content data is an AuthenticatedSafe */
1472 14           macStart = p;
1473 14 100         if ((rc = psParseAuthenticatedSafe(pool, cert, privKey, iwidePass, ipassLen,
1474 14           (unsigned char **) &p, (int32) (end - p))) < PS_SUCCESS)
1475             {
1476             psTraceIntCrypto("PKCS#12 AuthenticatedSafe parse failure %d\n", rc);
1477 4           goto ERR_FBUF;
1478             }
1479 10           macEnd = p;
1480              
1481             /* Integrity validation */
1482 10 50         if (integrity == PASSWORD_INTEGRITY)
1483             {
1484 10           mpassLen = (macPassLen * 2) + 2;
1485 10           memset(mwidePass, 0x0, mpassLen);
1486 36 100         for (i = 1, j = 0; i < mpassLen - 1; i += 2, j++)
1487             {
1488 26           mwidePass[i] = macPass[j];
1489             }
1490             /* MacData ::= SEQUENCE {
1491             mac DigestInfo,
1492             macSalt OCTET STRING,
1493             iterations INTEGER DEFAULT 1
1494             -- Note: The default is for historical reasons and its use is
1495             -- deprecated. A higher value, like 1024 is recommended. } */
1496 10 50         if ((rc = getAsnSequence(&p, (int32) (end - p), &tmplen)) < 0)
1497             {
1498             psTraceCrypto("Initial password integrity parse failure\n");
1499 0           goto ERR_FBUF;
1500             }
1501             /* DigestInfo ::= SEQUENCE {
1502             digestAlgorithm DigestAlgorithmIdentifier,
1503             digest Digest } */
1504 10 50         if ((rc = getAsnSequence(&p, (int32) (end - p), &tmplen)) < 0)
1505             {
1506             psTraceCrypto("Sequence password integrity parse failure\n");
1507 0           goto ERR_FBUF;
1508             }
1509 10 50         if ((rc = getAsnAlgorithmIdentifier(&p, (uint32) (end - p),
1510             &oi, &tmpint)) < 0)
1511             {
1512             psTraceCrypto("Algorithm password integrity parse failure\n");
1513 0           goto ERR_FBUF;
1514             }
1515 20           if ((*p++ != ASN_OCTET_STRING) ||
1516 10           getAsnLength(&p, (int32) (end - p), &tmplen) < 0)
1517             {
1518             psTraceCrypto("Octet digest password integrity parse failure\n");
1519 0           rc = PS_PARSE_FAIL;
1520 0           goto ERR_FBUF;
1521             }
1522 10           memcpy(digest, p, tmplen);
1523 10           p += tmplen;
1524 20           if ((*p++ != ASN_OCTET_STRING) ||
1525 10           getAsnLength(&p, (int32) (end - p), &tmplen) < 0)
1526             {
1527             psTraceCrypto("Octet macSalt password integrity parse failure\n");
1528 0           rc = PS_PARSE_FAIL;
1529 0           goto ERR_FBUF;
1530             }
1531 10 50         if (tmplen > 20)
1532             {
1533             psTraceCrypto("macSalt length too long\n");
1534 0           rc = PS_PARSE_FAIL;
1535 0           goto ERR_FBUF;
1536             }
1537 10           memcpy(macSalt, p, tmplen);
1538 10           p += tmplen;
1539             /* Iteration count */
1540 10 50         if (p != end)
1541             {
1542 10 50         if (getAsnInteger(&p, (int32) (end - p), &asnint) < 0)
1543             {
1544             psTraceCrypto("Iteration password integrity parse failure\n");
1545 0           rc = PS_PARSE_FAIL;
1546 0           goto ERR_FBUF;
1547             }
1548             }
1549             else
1550             {
1551 0           asnint = 0;
1552             }
1553 10 50         psAssert(p == end); /* That's all folks */
1554              
1555 10 50         if (oi == OID_SHA1_ALG)
1556             {
1557             /* When password integrity mode is used to secure a PFX PDU,
1558             an SHA-1 HMAC is computed on the BER-encoding of the contents
1559             of the content field of the authSafe field in the PFX PDU */
1560 10           macKeyLen = 20;
1561 10 50         if (pkcs12pbe(pool, mwidePass, mpassLen, macSalt, tmplen,
1562             asnint, PKCS12_MAC_ID, &macKey, &macKeyLen) < 0)
1563             {
1564             psTraceCrypto("Error generating pkcs12 hmac key\n");
1565 0           rc = PS_UNSUPPORTED_FAIL;
1566 0           goto ERR_FBUF;
1567             }
1568 10           digestLen = (uint32) (macEnd - macStart);
1569 10           psHmacSha1Init(&hmac, macKey, macKeyLen);
1570 10           psHmacSha1Update(&hmac, macStart, digestLen);
1571 10           psHmacSha1Final(&hmac, mac);
1572 10           psFree(macKey, pool);
1573 10           if (memcmp(digest, mac, SHA1_HASH_SIZE) != 0)
1574             {
1575             psTraceCrypto("CAUTION: PKCS#12 MAC did not validate\n");
1576             }
1577             }
1578             else
1579             {
1580             psTraceCrypto("PKCS#12 must use SHA1 HMAC validation\n");
1581 0           rc = PS_UNSUPPORTED_FAIL;
1582 0           goto ERR_FBUF;
1583             }
1584              
1585             }
1586 10           rc = PS_SUCCESS;
1587             ERR_FBUF:
1588 14           memset_s(iwidePass, sizeof(iwidePass), 0x0, sizeof(iwidePass));
1589 14           memset_s(mwidePass, sizeof(mwidePass), 0x0, sizeof(mwidePass));
1590 14           psFree(fileBuf, pool);
1591 15           return rc;
1592             }
1593              
1594             # endif /* USE_PKCS12 */
1595             # endif /* MATRIX_USE_FILE_SYSTEM */
1596              
1597             # endif /* USE_PKCS8 */
1598              
1599             # ifdef MATRIX_USE_FILE_SYSTEM
1600              
1601             # if defined(USE_PKCS5) && defined(USE_PBKDF1)
1602             /******************************************************************************/
1603             /*
1604             Convert an ASCII hex representation to a binary buffer.
1605             Decode enough data out of 'hex' buffer to produce 'binlen' bytes in 'bin'
1606             Two digits of ASCII hex map to the high and low nybbles (in that order),
1607             so this function assumes that 'hex' points to 2x 'binlen' bytes of data.
1608             Return the number of bytes processed from hex (2x binlen) or < 0 on error.
1609             */
1610 3           static int32 hexToBinary(unsigned char *hex, unsigned char *bin, int32 binlen)
1611             {
1612             unsigned char *end, c, highOrder;
1613              
1614 3           highOrder = 1;
1615 51 100         for (end = hex + binlen * 2; hex < end; hex++)
1616             {
1617 48           c = *hex;
1618 48 50         if ('0' <= c && c <= '9')
    100          
1619             {
1620 36           c -= '0';
1621             }
1622 12 50         else if ('a' <= c && c <= 'f')
    0          
1623             {
1624 0           c -= ('a' - 10);
1625             }
1626 12 50         else if ('A' <= c && c <= 'F')
    50          
1627             {
1628 12           c -= ('A' - 10);
1629             }
1630             else
1631             {
1632             psTraceCrypto("hexToBinary failure\n");
1633 0           return PS_FAILURE;
1634             }
1635 48 100         if (highOrder++ & 0x1)
1636             {
1637 24           *bin = c << 4;
1638             }
1639             else
1640             {
1641 24           *bin |= c;
1642 24           bin++;
1643             }
1644             }
1645 3           return binlen * 2;
1646             }
1647             # endif /* USE_PKCS5 && USE_PBKDF1 */
1648              
1649             # ifdef USE_RSA
1650 0           int32_t psPkcs1ParsePubFile(psPool_t *pool, const char *fileName, psRsaKey_t *key)
1651             {
1652             unsigned char *DERout;
1653             unsigned char sha1KeyHash[SHA1_HASH_SIZE];
1654             const unsigned char *p, *end;
1655             int32_t rc, oi;
1656             psSize_t DERlen, seqlen, plen;
1657              
1658             /* Had to tweak psPkcs1DecodePrivFile to accept PUBLIC KEY headers */
1659 0 0         if ((rc = psPkcs1DecodePrivFile(pool, fileName, NULL, &DERout, &DERlen))
1660             < PS_SUCCESS)
1661             {
1662 0           return rc;
1663             }
1664              
1665 0           p = DERout;
1666 0           end = p + DERlen;
1667              
1668 0 0         if (getAsnSequence(&p, (int32) (end - p), &seqlen) < 0)
1669             {
1670             psTraceCrypto("Couldn't parse PKCS#1 RSA public key file\n");
1671 0           goto pubKeyFail;
1672             }
1673 0 0         if (getAsnAlgorithmIdentifier(&p, (int32) (end - p), &oi, &plen) < 0)
1674             {
1675             psTraceCrypto("Couldn't parse PKCS#1 RSA public key file\n");
1676 0           goto pubKeyFail;
1677             }
1678 0 0         if (oi != OID_RSA_KEY_ALG)
1679             {
1680             psTraceCrypto("Couldn't parse PKCS#1 RSA public key file\n");
1681 0           goto pubKeyFail;
1682             }
1683 0 0         if (psRsaParseAsnPubKey(pool, &p, (int32) (end - p), key, sha1KeyHash) < 0)
1684             {
1685             psTraceCrypto("Couldn't parse PKCS#1 RSA public key file\n");
1686 0           goto pubKeyFail;
1687             }
1688              
1689 0           psFree(DERout, pool);
1690 0           return PS_SUCCESS;
1691              
1692             pubKeyFail:
1693 0           psFree(DERout, pool);
1694 0           return PS_PARSE_FAIL;
1695             }
1696             /******************************************************************************/
1697             /**
1698             Parse a PEM format private key file.
1699              
1700             @pre File must be a PEM format RSA keys.
1701             @return < 0 on error
1702             */
1703 134           int32_t psPkcs1ParsePrivFile(psPool_t *pool, const char *fileName,
1704             const char *password, psRsaKey_t *key)
1705             {
1706             unsigned char *DERout;
1707             int32_t rc;
1708             psSize_t DERlen;
1709              
1710             # ifdef USE_PKCS8
1711             psPubKey_t pubkey;
1712             # endif
1713              
1714 134 100         if ((rc = psPkcs1DecodePrivFile(pool, fileName, password, &DERout, &DERlen))
1715             < PS_SUCCESS)
1716             {
1717 1           return rc;
1718             }
1719              
1720 133 100         if ((rc = psRsaParsePkcs1PrivKey(pool, DERout, DERlen, key)) < 0)
1721             {
1722             # ifdef USE_PKCS8
1723             /* This logic works for processing PKCS#8 files because the above file
1724             and bin decodes will always leave the unprocessed buffer intact and
1725             the password protection is done in the internal ASN.1 encoding */
1726 132 100         if ((rc = psPkcs8ParsePrivBin(pool, DERout, DERlen, (char *) password,
1727             &pubkey)) < 0)
1728             {
1729 4           psFree(DERout, pool);
1730 4           return rc;
1731             }
1732 128           rc = psRsaCopyKey(key, &pubkey.key.rsa);
1733 128           psClearPubKey(&pubkey);
1734             # else
1735             psFree(DERout, pool);
1736             return rc;
1737             # endif
1738             }
1739              
1740 129           psFree(DERout, pool);
1741 134           return rc;
1742             }
1743             # endif /* USE_RSA */
1744              
1745             /******************************************************************************/
1746             /**
1747             Return the DER stream from a private key PEM file.
1748              
1749             Memory info:
1750             Caller must call psFree on DERout on function success
1751             */
1752 134           int32_t psPkcs1DecodePrivFile(psPool_t *pool, const char *fileName,
1753             const char *password, unsigned char **DERout, psSize_t *DERlen)
1754             {
1755             unsigned char *keyBuf, *dout;
1756             char *start, *end, *endTmp;
1757             int32 keyBufLen, rc;
1758 134           uint32 PEMlen = 0;
1759              
1760             # if defined(USE_PKCS5) && defined(USE_PBKDF1)
1761             psDes3_t dctx;
1762             psAesCbc_t actx;
1763             unsigned char passKey[32]; /* AES-256 max */
1764             unsigned char cipherIV[16]; /* AES-256 max */
1765 134           int32 tmp, encrypted = 0;
1766              
1767             static const char des3encryptHeader[] = "DEK-Info: DES-EDE3-CBC,";
1768             static const char aes128encryptHeader[] = "DEK-Info: AES-128-CBC,";
1769             # endif /* USE_PKCS5 && USE_PBKDF1 */
1770              
1771 134 50         if (fileName == NULL)
1772             {
1773             psTraceCrypto("No fileName passed to psPkcs1DecodePrivFile\n");
1774 0           return PS_ARG_FAIL;
1775             }
1776 134 50         if ((rc = psGetFileBuf(pool, fileName, &keyBuf, &keyBufLen)) < PS_SUCCESS)
1777             {
1778 0           return rc;
1779             }
1780 134           start = end = NULL;
1781              
1782             /* Check header and encryption parameters. */
1783 134 50         if (((start = strstr((char *) keyBuf, "-----BEGIN")) != NULL) &&
    50          
1784 134 50         ((start = strstr((char *) keyBuf, "PRIVATE KEY-----")) != NULL) &&
1785 134 50         ((end = strstr(start, "-----END")) != NULL) &&
1786             ((endTmp = strstr(end, "PRIVATE KEY-----")) != NULL))
1787             {
1788 134           start += strlen("PRIVATE KEY-----");
1789 268 50         while (*start == '\x0d' || *start == '\x0a')
    100          
1790             {
1791 134           start++;
1792             }
1793 134           PEMlen = (uint32) (end - start);
1794             }
1795 0 0         else if (((start = strstr((char *) keyBuf, "-----BEGIN")) != NULL) &&
    0          
1796 0 0         ((start = strstr((char *) keyBuf, "PUBLIC KEY-----")) != NULL) &&
1797 0 0         ((end = strstr(start, "-----END")) != NULL) &&
1798             ((endTmp = strstr(end, "PUBLIC KEY-----")) != NULL))
1799             {
1800 0           start += strlen("PUBLIC KEY-----");
1801 0 0         while (*start == '\x0d' || *start == '\x0a')
    0          
1802             {
1803 0           start++;
1804             }
1805 0           PEMlen = (uint32) (end - start);
1806             }
1807             else
1808             {
1809             psTraceCrypto("File buffer does not look to be in PKCS#1 PEM format\n");
1810 0           psFree(keyBuf, pool);
1811 0           return PS_PARSE_FAIL;
1812             }
1813              
1814 134 100         if (strstr((char *) keyBuf, "Proc-Type:") &&
    50          
1815 4           strstr((char *) keyBuf, "4,ENCRYPTED"))
1816             {
1817             # if defined(USE_PKCS5) && defined(USE_PBKDF1)
1818 4 100         if (password == NULL)
1819             {
1820             psTraceCrypto("No password given for encrypted private key file\n");
1821 1           psFree(keyBuf, pool);
1822 1           return PS_ARG_FAIL;
1823             }
1824 3 50         if ((start = strstr((char *) keyBuf, des3encryptHeader)) != NULL)
1825             {
1826 3           start += strlen(des3encryptHeader);
1827 3           encrypted = 1;
1828             /* we assume here that header points to at least 16 bytes of data */
1829 3           tmp = hexToBinary((unsigned char *) start, cipherIV, DES3_IVLEN);
1830             }
1831 0 0         else if ((start = strstr((char *) keyBuf, aes128encryptHeader))
1832             != NULL)
1833             {
1834 0           start += strlen(aes128encryptHeader);
1835 0           encrypted = 2;
1836             /* we assume here that header points to at least 32 bytes of data */
1837 0           tmp = hexToBinary((unsigned char *) start, cipherIV, 16);
1838             }
1839             else
1840             {
1841             psTraceCrypto("Unrecognized private key file encoding\n");
1842 0           psFree(keyBuf, pool);
1843 0           return PS_PARSE_FAIL;
1844             }
1845              
1846 3 50         if (tmp < 0)
1847             {
1848             psTraceCrypto("Invalid private key file salt\n");
1849 0           psFree(keyBuf, pool);
1850 0           return PS_FAILURE;
1851             }
1852 3           start += tmp;
1853 3 50         if (psPkcs5Pbkdf1((unsigned char *) password, strlen(password),
1854             cipherIV, 1, (unsigned char *) passKey) < 0)
1855             {
1856             psTraceCrypto("psPkcs5Pbkdf1 failed\n");
1857 0           psFree(keyBuf, pool);
1858 0           return PS_FAILURE;
1859             }
1860 3           PEMlen = (int32) (end - start);
1861             # else /* !USE_PKCS5 || !USE_PBKDF1 */
1862             /* The private key is encrypted, but PKCS5 support has been turned off */
1863             # ifndef USE_PKCS5
1864             psTraceCrypto("USE_PKCS5 must be enabled for key file password\n");
1865             # endif /* USE_PKCS5 */
1866             # ifndef USE_PBKDF1
1867             psTraceCrypto("USE_PBKDF1 must be enabled for key file password\n");
1868             # endif /* USE_PBKDF1 */
1869             psFree(keyBuf, pool);
1870             return PS_UNSUPPORTED_FAIL;
1871             # endif /* USE_PKCS5 && USE_PBKDF1 */
1872             }
1873              
1874             /* Take the raw input and do a base64 decode */
1875 133           dout = psMalloc(pool, PEMlen);
1876 133 50         if (dout == NULL)
1877             {
1878 0           psFree(keyBuf, pool);
1879 0           psError("Memory allocation error in psPkcs1DecodePrivFile\n");
1880 0           return PS_MEM_FAIL;
1881             }
1882 133           *DERlen = PEMlen;
1883 133 50         if ((rc = psBase64decode((unsigned char *) start, PEMlen, dout,
1884             DERlen)) < 0)
1885             {
1886             psTraceCrypto("Error base64 decode of private key\n");
1887             if (password)
1888             {
1889             psTraceCrypto("Is it possible the password is incorrect?\n");
1890             }
1891 0           psFree(dout, pool);
1892 0           psFree(keyBuf, pool);
1893 0           return rc;
1894             }
1895 133           psFree(keyBuf, pool);
1896              
1897             # if defined(USE_PKCS5) && defined(USE_PBKDF1)
1898 133 100         if (encrypted == 1 && password)
    50          
1899             {
1900 3           psDes3Init(&dctx, cipherIV, passKey);
1901 3           psDes3Decrypt(&dctx, dout, dout, *DERlen);
1902 3           memset_s(&dctx, sizeof(psDes3_t), 0x0, sizeof(psDes3_t));
1903             }
1904 133 50         if (encrypted == 2 && password)
    0          
1905             {
1906             /* AES 128 */
1907 0           psAesInitCBC(&actx, cipherIV, passKey, 16, PS_AES_DECRYPT);
1908 0           psAesDecryptCBC(&actx, dout, dout, *DERlen);
1909 0           memset_s(&actx, sizeof(psAesCbc_t), 0x0, sizeof(psAesCbc_t));
1910             }
1911             /* SECURITY - zero out keys when finished */
1912 133           memset_s(passKey, sizeof(passKey), 0x0, sizeof(passKey));
1913             # endif /* USE_PKCS5 && USE_PBKDF1 */
1914 133           *DERout = dout;
1915              
1916 134           return PS_SUCCESS;
1917             }
1918              
1919             # endif /* MATRIX_USE_FILE_SYSTEM */
1920             #endif /* USE_PRIVATE_KEY_PARSING */
1921             /******************************************************************************/
1922              
1923             /******************************************************************************/
1924             #ifdef USE_PKCS5
1925             # ifdef USE_PBKDF1
1926             /******************************************************************************/
1927             /*
1928             Generate a key given a password and salt value.
1929             PKCS#5 2.0 PBKDF1 key derivation format with MD5 and count == 1 per:
1930             http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html
1931              
1932             This key is compatible with the algorithm used by OpenSSL to encrypt keys
1933             generated with 'openssl genrsa'. If other encryption formats are used
1934             (for example PBKDF2), or an iteration count != 1 is used, they are not
1935             compatible with this simple implementation. OpenSSL provides many options
1936             for converting key formats to the one used here.
1937              
1938             A 3DES key is 24 bytes long, to generate it with this algorithm,
1939             we md5 hash the password and salt for the first 16 bytes. We then
1940             hash these first 16 bytes with the password and salt again, generating
1941             another 16 bytes. We take the first 16 bytes and 8 of the second 16 to
1942             form the 24 byte key.
1943              
1944             salt is assumed to point to 8 bytes of data
1945             key is assumed to point to 24 bytes of data
1946             */
1947 3           int32_t psPkcs5Pbkdf1(unsigned char *pass, uint32 passlen, unsigned char *salt,
1948             int32 iter, unsigned char *key)
1949             {
1950             int32_t rc;
1951             psDigestContext_t md;
1952             unsigned char md5[MD5_HASH_SIZE];
1953              
1954 3 50         psAssert(iter == 1);
1955              
1956 3           rc = psMd5Init(&md.md5);
1957 3 50         if (rc != PS_SUCCESS)
1958             {
1959             psTraceCrypto("psMd5Init failed. Please ensure non-FIPS mode.\n");
1960 0           return rc;
1961             }
1962 3           psMd5Update(&md.md5, pass, passlen);
1963 3           psMd5Update(&md.md5, salt, 8);
1964 3           psMd5Final(&md.md5, md5);
1965 3           memcpy(key, md5, MD5_HASH_SIZE);
1966              
1967 3           rc = psMd5Init(&md.md5);
1968 3 50         if (rc != PS_SUCCESS)
1969             {
1970             psTraceCrypto("psMd5Init failed. Please ensure non-FIPS mode.\n");
1971 0           return rc;
1972             }
1973              
1974 3           psMd5Update(&md.md5, md5, MD5_HASH_SIZE);
1975 3           psMd5Update(&md.md5, pass, passlen);
1976 3           psMd5Update(&md.md5, salt, 8);
1977 3           psMd5Final(&md.md5, md5);
1978 3           memcpy(key + MD5_HASH_SIZE, md5, 24 - MD5_HASH_SIZE);
1979              
1980 3           memset_s(md5, MD5_HASH_SIZE, 0x0, MD5_HASH_SIZE);
1981 3           memset_s(&md, sizeof(psDigestContext_t), 0x0, sizeof(psDigestContext_t));
1982 3           return PS_SUCCESS;
1983             }
1984             # endif /* USE_PBKDF1 */
1985              
1986             # if defined(USE_HMAC_SHA1)
1987             /******************************************************************************/
1988             /*
1989             Generate a key given a password, salt and iteration value.
1990             PKCS#5 2.0 PBKDF2 key derivation format with HMAC-SHA per:
1991             http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html
1992              
1993             Given a password, a salt, and an iteration count (rounds), generate a
1994             key suitable for encrypting data with 3DES, AES, etc.
1995             key should point to storage as large as kLen
1996             */
1997 0           void psPkcs5Pbkdf2(unsigned char *password, uint32 pLen,
1998             unsigned char *salt, uint32 sLen, int32 rounds,
1999             unsigned char *key, uint32 kLen)
2000             {
2001             int32 itts;
2002             uint32 blkno;
2003             unsigned long stored, left, i;
2004             unsigned char buf[2][SHA1_HASH_SIZE];
2005             psHmacSha1_t hmac;
2006              
2007 0 0         psAssert(password && salt && key && kLen);
    0          
    0          
    0          
2008              
2009 0           left = kLen;
2010 0           blkno = 1;
2011 0           stored = 0;
2012 0 0         while (left != 0)
2013             {
2014             /* process block number blkno */
2015 0           memset(buf[0], 0x0, SHA1_HASH_SIZE * 2);
2016              
2017             /* store current block number and increment for next pass */
2018 0           STORE32H(blkno, buf[1]);
2019 0           ++blkno;
2020              
2021             /* get PRF(P, S||int(blkno)) */
2022 0           psHmacSha1Init(&hmac, password, pLen);
2023 0           psHmacSha1Update(&hmac, salt, sLen);
2024 0           psHmacSha1Update(&hmac, buf[1], 4);
2025 0           psHmacSha1Final(&hmac, buf[0]);
2026              
2027             /* now compute repeated and XOR it in buf[1] */
2028 0           memcpy(buf[1], buf[0], SHA1_HASH_SIZE);
2029 0 0         for (itts = 1; itts < rounds; ++itts)
2030             {
2031 0           psHmacSha1Init(&hmac, password, pLen);
2032 0           psHmacSha1Update(&hmac, buf[0], SHA1_HASH_SIZE);
2033 0           psHmacSha1Final(&hmac, buf[0]);
2034 0 0         for (i = 0; i < SHA1_HASH_SIZE; i++)
2035             {
2036 0           buf[1][i] ^= buf[0][i];
2037             }
2038             }
2039             /* now emit upto x bytes of buf[1] to output */
2040 0 0         for (i = 0; i < SHA1_HASH_SIZE && left != 0; ++i)
    0          
2041             {
2042 0           key[stored++] = buf[1][i];
2043 0           --left;
2044             }
2045             }
2046              
2047 0           memset_s(buf, SHA1_HASH_SIZE * 2, 0x0, SHA1_HASH_SIZE * 2);
2048 0           memset_s(&hmac, sizeof(psHmacSha1_t), 0x0, sizeof(psHmacSha1_t));
2049 0           }
2050             # endif /* USE_HMAC && USE_SHA1 */
2051             #endif /* USE_PKCS5 */
2052              
2053             #if defined(USE_DH) && defined(MATRIX_USE_FILE_SYSTEM)
2054             /******************************************************************************/
2055             /**
2056             Extract Diffie-Hellman parameters from a PEM encoded file.
2057             This API decodes the PEM format and passes the ASN.1 encoded parameters
2058             to psPkcs3ParseDhParamBin() to parse the ASN.1.
2059              
2060             @param pool Memory pool
2061             @param[in] fileName File name of PEM encoded ASN.1 to load.
2062             @param[in,out] params Allocated parameter structure to receive parsed
2063             params.
2064             @return < on error.
2065             */
2066 0           int32_t psPkcs3ParseDhParamFile(psPool_t *pool, const char *fileName, psDhParams_t *params)
2067             {
2068             unsigned char *pemOut, *p;
2069             char *dhFileBuf, *start, *end;
2070             int32_t rc;
2071             psSize_t baseLen, pemOutLen;
2072             int32_t dhFileLen;
2073              
2074 0 0         if (!params || !fileName)
    0          
2075             {
2076 0           return PS_ARG_FAIL;
2077             }
2078             /* This is part of key assignment at startup. Base pool is fine here */
2079 0 0         if ((rc = psGetFileBuf(pool, fileName,
2080             (unsigned char **) &dhFileBuf, &dhFileLen)) < 0)
2081             {
2082 0           return rc;
2083             }
2084             /* Set end to end of file buffer */
2085 0           end = dhFileBuf + dhFileLen;
2086             /* Set start to start of token */
2087 0 0         if ((start = strstr(dhFileBuf, "-----BEGIN DH PARAMETERS-----")) == NULL)
2088             {
2089             psTraceStrCrypto("Error parsing dh file buffer header: %s\n", fileName);
2090 0           psFree(dhFileBuf, pool);
2091 0           return PS_PARSE_FAIL;
2092             }
2093             /* Move start to start of PEM data, skipping CR/LF */
2094 0           start += 29; /* strlen("-----BEGIN DH PARAMETERS-----"); */
2095 0 0         while (start < end && (*start == '\x0d' || *start == '\x0a'))
    0          
    0          
2096             {
2097 0           start++;
2098             }
2099             /* Set end to end token */
2100 0 0         if ((end = strstr(start, "-----END DH PARAMETERS-----")) == NULL)
2101             {
2102             psTraceStrCrypto("Error parsing dh file buffer footer: %s\n", fileName);
2103 0           psFree(dhFileBuf, pool);
2104 0           return PS_PARSE_FAIL;
2105             }
2106 0           baseLen = (uint16_t) (end - start);
2107              
2108 0           p = NULL;
2109 0           p = pemOut = psMalloc(pool, baseLen);
2110 0 0         if (p == NULL)
2111             {
2112 0           psError("Memory allocation error in psPkcs3ParseDhParamFile\n");
2113 0           psFree(dhFileBuf, pool);
2114 0           return PS_MEM_FAIL;
2115             }
2116              
2117 0           pemOutLen = baseLen;
2118 0 0         if (psBase64decode((unsigned char *) start, baseLen, p, &pemOutLen) != 0)
2119             {
2120 0           psFree(dhFileBuf, pool);
2121 0           psFree(pemOut, pool);
2122 0           return PS_PARSE_FAIL;
2123             }
2124 0           psFree(dhFileBuf, pool);
2125              
2126 0 0         if ((rc = psPkcs3ParseDhParamBin(pool, p, pemOutLen, params)) < 0)
2127             {
2128 0           psFree(pemOut, pool);
2129 0           return rc;
2130             }
2131 0           psFree(pemOut, pool);
2132 0           return 0;
2133             }
2134             #endif /* USE_DH && MATRIX_USE_FILE_SYSTEM */
2135              
2136             /******************************************************************************/
2137              
2138             /******************************************************************************/
2139             #if defined(USE_PKCS1_OAEP) || defined(USE_PKCS1_PSS)
2140             /*
2141             The reason we weren't able to create a callback structure for the hash
2142             routines was because of the Mac relocation build errors related to
2143             the register usage when assembly code is used in pstm
2144             */
2145             /******************************************************************************/
2146             /*
2147             Perform PKCS #1 Mask Generation Function (internal)
2148             pool Memory pool
2149             seed The seed for MGF1
2150             seedlen The length of the seed
2151             hash_idx The index of the hash desired
2152             mask [out] The destination
2153             masklen The length of the mask desired
2154             return 0 if successful
2155             */
2156 0           static int32 pkcs_1_mgf1(psPool_t *pool, const unsigned char *seed,
2157             unsigned long seedlen, int32 hash_idx, unsigned char *mask,
2158             unsigned long masklen)
2159             {
2160             unsigned long hLen, x;
2161             uint32 counter;
2162             psDigestContext_t md;
2163             unsigned char *buf;
2164              
2165 0 0         if ((seed == NULL) || (mask == NULL))
    0          
2166             {
2167 0           return -1;
2168             }
2169 0           hLen = 0;
2170             /*
2171             Get hash output size. Index has already been verified by caller so
2172             don't need 'else' error cases
2173             */
2174 0 0         if (hash_idx == PKCS1_SHA1_ID)
2175             {
2176 0           hLen = SHA1_HASH_SIZE;
2177             }
2178 0 0         else if (hash_idx == PKCS1_MD5_ID)
2179             {
2180 0           hLen = MD5_HASH_SIZE;
2181             # ifdef USE_SHA256
2182             }
2183 0 0         else if (hash_idx == PKCS1_SHA256_ID)
2184             {
2185 0           hLen = SHA256_HASH_SIZE;
2186             # endif
2187             # ifdef USE_SHA384
2188             }
2189 0 0         else if (hash_idx == PKCS1_SHA384_ID)
2190             {
2191 0           hLen = SHA384_HASH_SIZE;
2192             # endif
2193             # ifdef USE_SHA512
2194             }
2195 0 0         else if (hash_idx == PKCS1_SHA512_ID)
2196             {
2197 0           hLen = SHA512_HASH_SIZE;
2198             # endif
2199             }
2200             else
2201             {
2202 0           return PS_UNSUPPORTED_FAIL;
2203             }
2204              
2205 0           buf = psMalloc(pool, hLen);
2206 0 0         if (buf == NULL)
2207             {
2208             psTraceCrypto("Memory allocation error in MGF\n");
2209 0           return -1;
2210             }
2211             /*
2212             Start counter
2213             */
2214 0           counter = 0;
2215              
2216 0 0         while (masklen > 0)
2217             {
2218             /* handle counter */
2219 0           STORE32H(counter, buf);
2220 0           ++counter;
2221              
2222             /*
2223             Get hash of seed || counter
2224             */
2225 0 0         if (hash_idx == PKCS1_SHA1_ID)
2226             {
2227 0           psSha1Init(&md.sha1);
2228 0           psSha1Update(&md.sha1, seed, seedlen);
2229 0           psSha1Update(&md.sha1, buf, 4);
2230 0           psSha1Final(&md.sha1, buf);
2231             # ifdef USE_MD5
2232             }
2233 0 0         else if (hash_idx == PKCS1_MD5_ID)
2234             {
2235 0           psMd5Init(&md.md5);
2236 0           psMd5Update(&md.md5, seed, seedlen);
2237 0           psMd5Update(&md.md5, buf, 4);
2238 0           psMd5Final(&md.md5, buf);
2239             # endif /* USE_MD5 */
2240             # ifdef USE_SHA256
2241             }
2242 0 0         else if (hash_idx == PKCS1_SHA256_ID)
2243             {
2244 0           psSha256Init(&md.sha256);
2245 0           psSha256Update(&md.sha256, seed, seedlen);
2246 0           psSha256Update(&md.sha256, buf, 4);
2247 0           psSha256Final(&md.sha256, buf);
2248             # endif
2249             # ifdef USE_SHA384
2250             }
2251 0 0         else if (hash_idx == PKCS1_SHA384_ID)
2252             {
2253 0           psSha384Init(&md.sha384);
2254 0           psSha384Update(&md.sha384, seed, seedlen);
2255 0           psSha384Update(&md.sha384, buf, 4);
2256 0           psSha384Final(&md.sha384, buf);
2257             # endif
2258             # ifdef USE_SHA512
2259             }
2260 0 0         else if (hash_idx == PKCS1_SHA512_ID)
2261             {
2262 0           psSha512Init(&md.sha512);
2263 0           psSha512Update(&md.sha512, seed, seedlen);
2264 0           psSha512Update(&md.sha512, buf, 4);
2265 0           psSha512Final(&md.sha512, buf);
2266             # endif
2267             }
2268              
2269             /* store it */
2270 0 0         for (x = 0; x < hLen && masklen > 0; x++, masklen--)
    0          
2271             {
2272 0           *mask++ = buf[x];
2273             }
2274             }
2275              
2276 0           psFree(buf, pool);
2277 0           return PS_SUCCESS;
2278             }
2279             #endif /* defined(USE_PKCS1_OAEP) || defined(USE_PKCS1_PSS) */
2280              
2281              
2282             #ifdef USE_PKCS1_OAEP
2283             /******************************************************************************/
2284             /*
2285             PKCS #1 v2.00 OAEP encode
2286             pool Memory pool
2287             msg The data to encode
2288             msglen The length of the data to encode (octets)
2289             lparam A session or system parameter (can be NULL)
2290             lparamlen The length of the lparam data
2291             seed Reserved for vector testing. Should be NULL
2292             seedLen Reserved for vector testing. Should be 0
2293             modulus_bitlen The bit length of the RSA modulus
2294             hash_idx The index of the hash desired (see psHashList table above)
2295             out [out] The destination for the encoded data
2296             outlen [in/out] The max size and resulting size of the encoded data
2297              
2298             return 0 if successful, -1 on failure
2299             */
2300 0           int32 psPkcs1OaepEncode(psPool_t *pool, const unsigned char *msg, uint32 msglen,
2301             const unsigned char *lparam, uint32 lparamlen,
2302             unsigned char *seed, uint32 seedLen,
2303             uint32 modulus_bitlen, int32 hash_idx,
2304             unsigned char *out, psSize_t *outlen)
2305             {
2306             unsigned char *DB, *lseed, *mask;
2307             uint32 hLen, x, y, modulus_len;
2308             int32 err;
2309             psDigestContext_t md;
2310              
2311 0 0         if ((msg == NULL) || (out == NULL) || (outlen == NULL) || (hash_idx < 0))
    0          
    0          
    0          
2312             {
2313             psTraceStrCrypto("Bad parameter to OAEP encode\n", NULL);
2314 0           return PS_ARG_FAIL;
2315             }
2316             /*
2317             Verify hash routines
2318             */
2319 0 0         if (hash_idx == PKCS1_SHA1_ID)
2320             {
2321 0           hLen = SHA1_HASH_SIZE;
2322             }
2323 0 0         else if (hash_idx == PKCS1_MD5_ID)
2324             {
2325             # ifdef USE_MD5
2326 0           hLen = MD5_HASH_SIZE;
2327             # else
2328             psTraceCrypto("MD5 not supported in this build.");
2329             psTraceCrypto(" Please enable USE_MD5\n");
2330             return PS_UNSUPPORTED_FAIL;
2331             # endif /* USE_MD5 */
2332             }
2333             else
2334             {
2335             psTraceStrCrypto("Bad hash index to OAEP encode\n", NULL);
2336 0           return PS_ARG_FAIL;
2337             }
2338             /*
2339             Seed should be generated randomly below but this helps for test vectors
2340             */
2341 0 0         if (seed != NULL && seedLen != hLen)
    0          
2342             {
2343             psTraceIntCrypto("Seed must be length of %d\n", hLen);
2344 0           return PS_ARG_FAIL;
2345             }
2346              
2347 0 0         modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
2348              
2349             /*
2350             Test message size
2351             */
2352 0 0         if ((2 * hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2 * hLen - 2)))
    0          
2353             {
2354             psTraceStrCrypto("Bad message size to OAEP encode\n", NULL);
2355 0           return PS_LIMIT_FAIL;
2356             }
2357              
2358             /*
2359             Allocate ram for DB/mask/salt of size modulus_len
2360             */
2361 0           lseed = NULL;
2362 0           DB = psMalloc(pool, modulus_len);
2363 0           mask = psMalloc(pool, modulus_len);
2364 0 0         if (DB == NULL || mask == NULL)
    0          
2365             {
2366 0 0         if (DB != NULL)
2367             {
2368 0           psFree(DB, pool);
2369             }
2370 0 0         if (mask != NULL)
2371             {
2372 0           psFree(mask, pool);
2373             }
2374             psTraceCrypto("Memory allocation error in OAEP encode\n");
2375 0           return PS_MEM_FAIL;
2376             }
2377              
2378             /*
2379             Create lhash for DB block format:
2380              
2381             DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes
2382             */
2383 0           x = modulus_len;
2384              
2385 0 0         if (lparam != NULL)
2386             {
2387 0 0         if (hash_idx == PKCS1_SHA1_ID)
2388             {
2389 0           psSha1Init(&md.sha1);
2390 0           psSha1Update(&md.sha1, lparam, lparamlen);
2391 0           psSha1Final(&md.sha1, DB);
2392             }
2393             # ifdef USE_MD5
2394             else
2395             {
2396 0           psMd5Init(&md.md5);
2397 0           psMd5Update(&md.md5, lparam, lparamlen);
2398 0           psMd5Final(&md.md5, DB);
2399             }
2400             # endif /* USE_MD5 */
2401             }
2402             else
2403             {
2404             /* can't pass hash a NULL so use DB with zero length */
2405 0 0         if (hash_idx == PKCS1_SHA1_ID)
2406             {
2407 0           psSha1Init(&md.sha1);
2408 0           psSha1Update(&md.sha1, DB, 0);
2409 0           psSha1Final(&md.sha1, DB);
2410             }
2411             # ifdef USE_MD5
2412             else
2413             {
2414 0           psMd5Init(&md.md5);
2415 0           psMd5Update(&md.md5, DB, 0);
2416 0           psMd5Final(&md.md5, DB);
2417             }
2418             # endif /* USE_MD5 */
2419             }
2420              
2421             /*
2422             Append PS then 0x01 (to lhash)
2423             */
2424 0           x = hLen;
2425 0           y = modulus_len - msglen - 2 * hLen - 2;
2426 0           memset(DB + x, 0, y);
2427 0           x += y;
2428              
2429 0           DB[x++] = 0x01;
2430              
2431             /*
2432             Message (length = msglen)
2433             */
2434 0           memcpy(DB + x, msg, msglen);
2435 0           x += msglen;
2436              
2437             /*
2438             Use psGetPrngLocked to choose a random seed (if not provided)
2439             */
2440 0 0         if (seed != NULL)
2441             {
2442 0           lseed = seed;
2443             }
2444             else
2445             {
2446 0           lseed = psMalloc(pool, hLen);
2447 0 0         if (lseed == NULL)
2448             {
2449 0           err = PS_MEM_FAIL;
2450 0           goto LBL_ERR;
2451             }
2452 0 0         if (psGetPrngLocked(lseed, hLen, NULL) != (int32) hLen)
2453             {
2454             psTraceCrypto("psGetPrngLocked fail in OAEP encode\n");
2455 0           err = PS_PLATFORM_FAIL;
2456 0           goto LBL_ERR;
2457             }
2458             }
2459              
2460             /*
2461             Compute MGF1 of seed (k - hlen - 1)
2462             */
2463 0 0         if ((err = pkcs_1_mgf1(pool, lseed, hLen, hash_idx, mask,
2464 0           modulus_len - hLen - 1)) != PS_SUCCESS)
2465             {
2466             psTraceStrCrypto("MGF for seed failed in OAEP encode\n", NULL);
2467 0           goto LBL_ERR;
2468             }
2469              
2470             /*
2471             xor against DB
2472             */
2473 0 0         for (y = 0; y < (modulus_len - hLen - 1); y++)
2474             {
2475 0           DB[y] ^= mask[y];
2476             }
2477              
2478             /*
2479             Compute MGF1 of maskedDB (hLen)
2480             */
2481 0 0         if ((err = pkcs_1_mgf1(pool, DB, modulus_len - hLen - 1, hash_idx,
2482             mask, hLen)) != PS_SUCCESS)
2483             {
2484             psTraceStrCrypto("MGF for DB failed in OAEP encode\n", NULL);
2485 0           goto LBL_ERR;
2486             }
2487              
2488             /*
2489             XOR against seed
2490             */
2491 0 0         for (y = 0; y < hLen; y++)
2492             {
2493 0           lseed[y] ^= mask[y];
2494             }
2495              
2496             /*
2497             Create string of length modulus_len
2498             */
2499 0 0         if (*outlen < modulus_len)
2500             {
2501             psTraceStrCrypto("Bad outlen in OAEP encode\n", NULL);
2502 0           err = -1;
2503 0           goto LBL_ERR;
2504             }
2505              
2506             /*
2507             Start output which is 0x00 || maskedSeed || maskedDB
2508             */
2509 0           x = 0;
2510 0           out[x++] = 0x00;
2511 0           memcpy(out + x, lseed, hLen);
2512 0           x += hLen;
2513 0           memcpy(out + x, DB, modulus_len - hLen - 1);
2514 0           x += modulus_len - hLen - 1;
2515              
2516 0           *outlen = x;
2517              
2518 0           err = PS_SUCCESS;
2519              
2520             LBL_ERR:
2521 0 0         if (seed == NULL)
2522             {
2523 0           psFree(lseed, pool);
2524             }
2525 0           psFree(mask, pool);
2526 0           psFree(DB, pool);
2527              
2528 0           return err;
2529             }
2530              
2531             /******************************************************************************/
2532             /*
2533             PKCS #1 v2.00 OAEP decode
2534             pool Memory pool
2535             msg The encoded data to decode
2536             msglen The length of the encoded data (octets)
2537             lparam The session or system data (can be NULL)
2538             lparamlen The length of the lparam
2539             modulus_bitlen The bit length of the RSA modulus
2540             hash_idx The index of the hash desired
2541             out [out] Destination of decoding
2542             outlen [in/out] The max size and resulting size of the decoding
2543              
2544             return 0 if successful
2545             */
2546 0           int32 psPkcs1OaepDecode(psPool_t *pool, const unsigned char *msg, uint32 msglen,
2547             const unsigned char *lparam, uint32 lparamlen,
2548             uint32 modulus_bitlen, int32 hash_idx,
2549             unsigned char *out, psSize_t *outlen)
2550             {
2551             unsigned char *DB, *seed, *mask;
2552             uint32 hLen, x, y, modulus_len;
2553             int32 err;
2554             psDigestContext_t md;
2555              
2556 0 0         if ((msg == NULL) || (out == NULL) || (outlen == NULL) || (hash_idx < 0))
    0          
    0          
    0          
2557             {
2558             psTraceCrypto("Bad parameter to OAEP decode\n");
2559 0           return PS_ARG_FAIL;
2560             }
2561             /*
2562             Verify hash routines
2563             */
2564 0 0         if (hash_idx == PKCS1_SHA1_ID)
2565             {
2566 0           hLen = SHA1_HASH_SIZE;
2567             }
2568 0 0         else if (hash_idx == PKCS1_MD5_ID)
2569             {
2570             # ifdef USE_MD5
2571 0           hLen = MD5_HASH_SIZE;
2572             # else
2573             psTraceCrypto("MD5 not supported in this build.");
2574             psTraceCrypto(" Please enable USE_MD5\n");
2575             return PS_UNSUPPORTED_FAIL;
2576             # endif /* USE_MD5 */
2577             }
2578             else
2579             {
2580             psTraceStrCrypto("Bad hash index to OAEP decode\n", NULL);
2581 0           return PS_ARG_FAIL;
2582             }
2583              
2584 0 0         modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
2585              
2586             /*
2587             Test hash/message size
2588             */
2589 0 0         if ((2 * hLen >= (modulus_len - 2)) || (msglen != modulus_len))
    0          
2590             {
2591             psTraceCrypto("Message/Modulus length mismatch in OAEP decode\n");
2592 0           return PS_LIMIT_FAIL;
2593             }
2594              
2595             /*
2596             Allocate ram for DB/mask/salt of size modulus_len
2597             */
2598 0           DB = psMalloc(pool, modulus_len);
2599 0           mask = psMalloc(pool, modulus_len);
2600 0           seed = psMalloc(pool, hLen);
2601 0 0         if (DB == NULL || mask == NULL || seed == NULL)
    0          
    0          
2602             {
2603 0 0         if (DB != NULL)
2604             {
2605 0           psFree(DB, pool);
2606             }
2607 0 0         if (mask != NULL)
2608             {
2609 0           psFree(mask, pool);
2610             }
2611 0 0         if (seed != NULL)
2612             {
2613 0           psFree(seed, pool);
2614             }
2615             psTraceCrypto("Memory allocation error in OAEP decode\n");
2616 0           return -1;
2617             }
2618              
2619             /*
2620             It's now in the form
2621              
2622             0x00 || maskedseed || maskedDB
2623              
2624             1 || hLen || modulus_len - hLen - 1
2625             */
2626 0 0         if (msg[0] != 0x00)
2627             {
2628             psTraceCrypto("Message format error in OAEP decode\n");
2629 0           err = PS_FAILURE;
2630 0           goto LBL_ERR;
2631             }
2632              
2633             /*
2634             Now read the masked seed
2635             */
2636 0           x = 1;
2637 0           memcpy(seed, msg + x, hLen);
2638 0           x += hLen;
2639              
2640             /*
2641             Now read the masked DB
2642             */
2643 0           memcpy(DB, msg + x, modulus_len - hLen - 1);
2644 0           x += modulus_len - hLen - 1;
2645              
2646             /*
2647             Compute MGF1 of maskedDB (hLen)
2648             */
2649 0 0         if ((err = pkcs_1_mgf1(pool, DB, modulus_len - hLen - 1, hash_idx,
2650             mask, hLen)) != PS_SUCCESS)
2651             {
2652             psTraceCrypto("MGF for DB failed in OAEP decode\n");
2653 0           goto LBL_ERR;
2654             }
2655              
2656             /*
2657             XOR against seed
2658             */
2659 0 0         for (y = 0; y < hLen; y++)
2660             {
2661 0           seed[y] ^= mask[y];
2662             }
2663              
2664             /*
2665             Compute MGF1 of seed (k - hlen - 1)
2666             */
2667 0 0         if ((err = pkcs_1_mgf1(pool, seed, hLen, hash_idx, mask,
2668 0           modulus_len - hLen - 1)) != PS_SUCCESS)
2669             {
2670             psTraceCrypto("MGF for seed failed in OAEP decode\n");
2671 0           goto LBL_ERR;
2672             }
2673              
2674             /*
2675             xor against DB
2676             */
2677 0 0         for (y = 0; y < (modulus_len - hLen - 1); y++)
2678             {
2679 0           DB[y] ^= mask[y];
2680             }
2681              
2682             /*
2683             compute lhash and store it in seed [reuse temps!]
2684              
2685             DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes
2686             */
2687 0           x = modulus_len;
2688              
2689 0 0         if (lparam != NULL)
2690             {
2691 0 0         if (hash_idx == PKCS1_SHA1_ID)
2692             {
2693 0           psSha1Init(&md.sha1);
2694 0           psSha1Update(&md.sha1, lparam, lparamlen);
2695 0           psSha1Final(&md.sha1, seed);
2696             }
2697             # ifdef USE_MD5
2698             else
2699             {
2700 0           psMd5Init(&md.md5);
2701 0           psMd5Update(&md.md5, lparam, lparamlen);
2702 0           psMd5Final(&md.md5, seed);
2703             }
2704             # endif /* USE_MD5 */
2705             }
2706             else
2707             {
2708             /* can't pass hash routine a NULL so use DB with zero length */
2709 0 0         if (hash_idx == PKCS1_SHA1_ID)
2710             {
2711 0           psSha1Init(&md.sha1);
2712 0           psSha1Update(&md.sha1, DB, 0);
2713 0           psSha1Final(&md.sha1, seed);
2714             }
2715             # ifdef USE_MD5
2716             else
2717             {
2718 0           psMd5Init(&md.md5);
2719 0           psMd5Update(&md.md5, DB, 0);
2720 0           psMd5Final(&md.md5, seed);
2721             }
2722             # endif /* USE_MD5 */
2723             }
2724              
2725             /*
2726             Compare the lhash'es
2727             */
2728 0 0         if (memcmp(seed, DB, hLen) != 0)
2729             {
2730             psTraceCrypto("Seed/DB mismatch in OAEP decode\n");
2731 0           err = -1;
2732 0           goto LBL_ERR;
2733             }
2734              
2735             /*
2736             Now zeroes before a 0x01
2737             */
2738 0 0         for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++)
    0          
2739             {
2740             /* step... */
2741             }
2742              
2743             /*
2744             Error out if wasn't 0x01
2745             */
2746 0 0         if (x == (modulus_len - hLen - 1) || DB[x] != 0x01)
    0          
2747             {
2748             psTraceCrypto("DB format error in OAEP decode\n");
2749 0           err = -1;
2750 0           goto LBL_ERR;
2751             }
2752              
2753             /*
2754             Rest is the message (and skip 0x01)
2755             */
2756 0 0         if ((modulus_len - hLen - 1) - ++x > *outlen)
2757             {
2758             psTraceCrypto("Bad outlen in OAEP decode\n");
2759 0           err = -1;
2760 0           goto LBL_ERR;
2761             }
2762              
2763             /*
2764             Copy message
2765             */
2766 0           *outlen = (modulus_len - hLen - 1) - x;
2767 0           memcpy(out, DB + x, modulus_len - hLen - 1 - x);
2768 0           x += modulus_len - hLen - 1;
2769              
2770 0           err = PS_SUCCESS;
2771             LBL_ERR:
2772              
2773 0           psFree(seed, pool);
2774 0           psFree(mask, pool);
2775 0           psFree(DB, pool);
2776              
2777 0           return err;
2778             }
2779             #endif /* USE_PKCS1_OAEP */
2780             /******************************************************************************/
2781              
2782             #ifdef USE_PKCS1_PSS
2783             /******************************************************************************/
2784             /*
2785             PKCS #1 v2.00 Signature Encoding
2786             @param msghash The hash to encode
2787             @param msghashlen The length of the hash (octets)
2788             @param saltlen The length of the salt desired (octets)
2789             @param hash_idx The index of the hash desired
2790             @param modulus_bitlen The bit length of the RSA modulus
2791             @param out [out] The destination of the encoding
2792             @param outlen [in/out] The max size and resulting size of the encoded data
2793             @return CRYPT_OK if successful
2794             */
2795 0           int32 psPkcs1PssEncode(psPool_t *pool, const unsigned char *msghash,
2796             uint32 msghashlen, unsigned char *tsalt, uint32 saltlen,
2797             int32 hash_idx, uint32 modulus_bitlen, unsigned char *out,
2798             psSize_t *outlen)
2799             {
2800             unsigned char *DB, *mask, *salt, *hash;
2801             uint32 x, y, hLen, modulus_len;
2802             int32 err;
2803             psDigestContext_t md;
2804              
2805 0 0         if ((msghash == NULL) || (out == NULL) || (outlen == NULL))
    0          
    0          
2806             {
2807             psTraceCrypto("Bad parameter to PSS encode\n");
2808 0           return PS_ARG_FAIL;
2809             }
2810              
2811 0 0         if (hash_idx == PKCS1_SHA1_ID)
2812             {
2813 0           hLen = SHA1_HASH_SIZE;
2814             }
2815 0 0         else if (hash_idx == PKCS1_MD5_ID)
2816             {
2817             # ifdef USE_MD5
2818 0           hLen = MD5_HASH_SIZE;
2819             # else
2820             psTraceCrypto("MD5 not supported in this build.");
2821             psTraceCrypto(" Please enable USE_MD5\n");
2822             return PS_UNSUPPORTED_FAIL;
2823             # endif /* USE_MD5 */
2824             # ifdef USE_SHA256
2825             }
2826 0 0         else if (hash_idx == PKCS1_SHA256_ID)
2827             {
2828 0           hLen = SHA256_HASH_SIZE;
2829             # endif
2830             }
2831             else
2832             {
2833             psTraceStrCrypto("Bad hash index to PSS encode\n", NULL);
2834 0           return PS_ARG_FAIL;
2835             }
2836              
2837 0 0         modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
2838              
2839             /* check sizes */
2840 0 0         if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2))
    0          
2841             {
2842             psTraceCrypto("Bad saltlen or modulus len to PSS encode\n");
2843 0           return PS_ARG_FAIL;
2844             }
2845              
2846             /* allocate ram for DB/mask/salt/hash of size modulus_len */
2847 0           err = PS_MEM_FAIL;
2848 0 0         if ((DB = psMalloc(pool, modulus_len)) == NULL)
2849             {
2850 0           return err;
2851             }
2852 0           memset(DB, 0x0, modulus_len);
2853 0 0         if ((mask = psMalloc(pool, modulus_len)) == NULL)
2854             {
2855 0           goto LBL_DB;
2856             }
2857 0           memset(mask, 0x0, modulus_len);
2858 0 0         if ((salt = psMalloc(pool, modulus_len)) == NULL)
2859             {
2860 0           goto LBL_MASK;
2861             }
2862 0           memset(salt, 0x0, modulus_len);
2863 0 0         if ((hash = psMalloc(pool, modulus_len)) == NULL)
2864             {
2865 0           goto LBL_SALT;
2866             }
2867 0           memset(hash, 0x0, modulus_len);
2868              
2869             /* generate random salt */
2870 0 0         if (saltlen > 0)
2871             {
2872 0 0         if (tsalt != NULL)
2873             {
2874 0           memcpy(salt, tsalt, saltlen);
2875             }
2876             else
2877             {
2878 0 0         if (psGetPrngLocked(salt, saltlen, NULL) != (int32) saltlen)
2879             {
2880 0           err = PS_PLATFORM_FAIL;
2881 0           goto LBL_ERR;
2882             }
2883             }
2884             }
2885              
2886             /* M = (eight) 0x00 || msghash || salt, hash = H(M) */
2887 0 0         if (hash_idx == PKCS1_SHA1_ID)
2888             {
2889 0           psSha1Init(&md.sha1);
2890 0           psSha1Update(&md.sha1, DB, 8); /* 8 0's */
2891 0           psSha1Update(&md.sha1, msghash, msghashlen);
2892 0           psSha1Update(&md.sha1, salt, saltlen);
2893 0           psSha1Final(&md.sha1, hash);
2894             }
2895             # ifdef USE_MD5
2896 0 0         if (hash_idx == PKCS1_MD5_ID)
2897             {
2898 0           psMd5Init(&md.md5);
2899 0           psMd5Update(&md.md5, DB, 8); /* 8 0's */
2900 0           psMd5Update(&md.md5, msghash, msghashlen);
2901 0           psMd5Update(&md.md5, salt, saltlen);
2902 0           psMd5Final(&md.md5, hash);
2903             }
2904             # endif /* USE_MD5 */
2905             # ifdef USE_SHA256
2906 0 0         if (hash_idx == PKCS1_SHA256_ID)
2907             {
2908 0           psSha256Init(&md.sha256);
2909 0           psSha256Update(&md.sha256, DB, 8); /* 8 0's */
2910 0           psSha256Update(&md.sha256, msghash, msghashlen);
2911 0           psSha256Update(&md.sha256, salt, saltlen);
2912 0           psSha256Final(&md.sha256, hash);
2913             }
2914             # endif
2915              
2916             /* generate DB = PS || 0x01 || salt
2917             PS == modulus_len - saltlen - hLen - 2 zero bytes */
2918 0           x = 0;
2919 0           memset(DB + x, 0, modulus_len - saltlen - hLen - 2);
2920 0           x += modulus_len - saltlen - hLen - 2;
2921 0           DB[x++] = 0x01;
2922 0           memcpy(DB + x, salt, saltlen);
2923 0           x += saltlen;
2924              
2925             /* generate mask of length modulus_len - hLen - 1 from hash */
2926 0 0         if ((err = pkcs_1_mgf1(pool, hash, hLen, hash_idx, mask,
2927 0           modulus_len - hLen - 1)) != PS_SUCCESS)
2928             {
2929 0           goto LBL_ERR;
2930             }
2931              
2932             /* xor against DB */
2933 0 0         for (y = 0; y < (modulus_len - hLen - 1); y++)
2934             {
2935 0           DB[y] ^= mask[y];
2936             }
2937              
2938             /* output is DB || hash || 0xBC */
2939 0 0         if (*outlen < modulus_len)
2940             {
2941 0           *outlen = modulus_len;
2942 0           err = PS_LIMIT_FAIL;
2943 0           goto LBL_ERR;
2944             }
2945              
2946             /* DB len = modulus_len - hLen - 1 */
2947 0           y = 0;
2948 0           memcpy(out + y, DB, modulus_len - hLen - 1);
2949 0           y += modulus_len - hLen - 1;
2950              
2951             /* hash */
2952 0           memcpy(out + y, hash, hLen);
2953 0           y += hLen;
2954              
2955             /* 0xBC */
2956 0           out[y] = 0xBC;
2957              
2958             /* now clear the 8*modulus_len - modulus_bitlen most significant bits */
2959 0           out[0] &= 0xFF >> ((modulus_len << 3) - (modulus_bitlen - 1));
2960              
2961             /* store output size */
2962 0           *outlen = modulus_len;
2963 0           err = PS_SUCCESS;
2964              
2965 0           LBL_ERR: psFree(hash, pool);
2966 0           LBL_SALT: psFree(salt, pool);
2967 0           LBL_MASK: psFree(mask, pool);
2968 0           LBL_DB: psFree(DB, pool);
2969              
2970 0           return err;
2971             }
2972              
2973             /******************************************************************************/
2974             /**
2975             PKCS #1 v2.00 PSS decode
2976             @param msghash The hash to verify
2977             @param msghashlen The length of the hash (octets)
2978             @param sig The signature data (encoded data)
2979             @param siglen The length of the signature data (octets)
2980             @param saltlen The length of the salt used (octets)
2981             @param hash_idx The index of the hash desired
2982             @param modulus_bitlen The bit length of the RSA modulus
2983             @param res [out] The result of the comparison, 1==valid, 0==invalid
2984              
2985             */
2986 0           int32 psPkcs1PssDecode(psPool_t *pool, const unsigned char *msghash,
2987             uint32 msghashlen, const unsigned char *sig, uint32 siglen,
2988             uint32 saltlen, int32 hash_idx, uint32 modulus_bitlen, int32 *res)
2989             {
2990             unsigned char *DB, *mask, *salt, *hash;
2991             uint32 x, y, hLen, modulus_len;
2992             int32 err;
2993             psDigestContext_t md;
2994              
2995 0 0         if ((msghash == NULL) || (res == NULL))
    0          
2996             {
2997             psTraceCrypto("Bad parameters to psPkcs1PssDecode\n");
2998 0           return PS_ARG_FAIL;
2999             }
3000              
3001             /* default to invalid */
3002 0           *res = 0;
3003              
3004 0 0         if (hash_idx == PKCS1_SHA1_ID)
3005             {
3006 0           hLen = SHA1_HASH_SIZE;
3007             }
3008 0 0         else if (hash_idx == PKCS1_MD5_ID)
3009             {
3010             # ifdef USE_MD5
3011 0           hLen = MD5_HASH_SIZE;
3012             # else
3013             psTraceCrypto("MD5 not supported in this build.");
3014             psTraceCrypto(" Please enable USE_MD5\n");
3015             return PS_UNSUPPORTED_FAIL;
3016             # endif /* USE_MD5 */
3017             # ifdef USE_SHA256
3018             }
3019 0 0         else if (hash_idx == PKCS1_SHA256_ID)
3020             {
3021 0           hLen = SHA256_HASH_SIZE;
3022             # endif
3023             # ifdef USE_SHA384
3024             }
3025 0 0         else if (hash_idx == PKCS1_SHA384_ID)
3026             {
3027 0           hLen = SHA384_HASH_SIZE;
3028             # endif
3029             # ifdef USE_SHA512
3030             }
3031 0 0         else if (hash_idx == PKCS1_SHA512_ID)
3032             {
3033 0           hLen = SHA512_HASH_SIZE;
3034             # endif
3035             }
3036             else
3037             {
3038             psTraceStrCrypto("Bad hash index to PSS decode\n", NULL);
3039 0           return PS_ARG_FAIL;
3040             }
3041              
3042 0 0         modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
3043              
3044             /* check sizes */
3045 0 0         if ((saltlen > modulus_len) ||
    0          
3046 0 0         (modulus_len < hLen + saltlen + 2) || (siglen != modulus_len))
3047             {
3048             psTraceCrypto("Bad saltlen or modulus len to PSS decode\n");
3049 0           return PS_ARG_FAIL;
3050             }
3051              
3052             /* allocate ram for DB/mask/salt/hash of size modulus_len */
3053 0           err = PS_MEM_FAIL;
3054 0 0         if ((DB = psMalloc(pool, modulus_len)) == NULL)
3055             {
3056 0           return err;
3057             }
3058 0           memset(DB, 0x0, modulus_len);
3059 0 0         if ((mask = psMalloc(pool, modulus_len)) == NULL)
3060             {
3061 0           goto LBL_DB;
3062             }
3063 0           memset(mask, 0x0, modulus_len);
3064 0 0         if ((salt = psMalloc(pool, modulus_len)) == NULL)
3065             {
3066 0           goto LBL_MASK;
3067             }
3068 0           memset(salt, 0x0, modulus_len);
3069 0 0         if ((hash = psMalloc(pool, modulus_len)) == NULL)
3070             {
3071 0           goto LBL_SALT;
3072             }
3073 0           memset(hash, 0x0, modulus_len);
3074              
3075             /* ensure the 0xBC byte */
3076 0 0         if (sig[siglen - 1] != 0xBC)
3077             {
3078 0           err = PS_FAILURE;
3079 0           goto LBL_ERR;
3080             }
3081              
3082             /* copy out the DB */
3083 0           x = 0;
3084 0           memcpy(DB, sig + x, modulus_len - hLen - 1);
3085 0           x += modulus_len - hLen - 1;
3086              
3087             /* copy out the hash */
3088 0           memcpy(hash, sig + x, hLen);
3089 0           x += hLen;
3090              
3091             /* check the MSB */
3092 0 0         if ((sig[0] & ~(0xFF >> ((modulus_len << 3) - (modulus_bitlen - 1)))) != 0)
3093             {
3094 0           err = PS_FAILURE;
3095 0           goto LBL_ERR;
3096             }
3097              
3098             /* generate mask of length modulus_len - hLen - 1 from hash */
3099 0 0         if ((err = pkcs_1_mgf1(pool, hash, hLen, hash_idx, mask,
3100 0           modulus_len - hLen - 1)) != PS_SUCCESS)
3101             {
3102 0           goto LBL_ERR;
3103             }
3104              
3105             /* xor against DB */
3106 0 0         for (y = 0; y < (modulus_len - hLen - 1); y++)
3107             {
3108 0           DB[y] ^= mask[y];
3109             }
3110              
3111             /* now clear the first byte [make sure smaller than modulus] */
3112 0           DB[0] &= 0xFF >> ((modulus_len << 3) - (modulus_bitlen - 1));
3113              
3114             /* DB = PS || 0x01 || salt,
3115             PS == modulus_len - saltlen - hLen - 2 zero bytes */
3116              
3117             /* check for zeroes and 0x01 */
3118 0 0         for (x = 0; x < modulus_len - saltlen - hLen - 2; x++)
3119             {
3120 0 0         if (DB[x] != 0x00)
3121             {
3122 0           err = PS_FAILURE;
3123 0           goto LBL_ERR;
3124             }
3125             }
3126              
3127             /* check for the 0x01 */
3128 0 0         if (DB[x++] != 0x01)
3129             {
3130 0           err = PS_FAILURE;
3131 0           goto LBL_ERR;
3132             }
3133              
3134             /* M = (eight) 0x00 || msghash || salt, mask = H(M) */
3135 0 0         if (hash_idx == PKCS1_SHA1_ID)
3136             {
3137 0           psSha1Init(&md.sha1);
3138 0           memset(mask, 0x0, 8);
3139 0           psSha1Update(&md.sha1, mask, 8);
3140 0           psSha1Update(&md.sha1, msghash, msghashlen);
3141 0           psSha1Update(&md.sha1, DB + x, saltlen);
3142 0           psSha1Final(&md.sha1, mask);
3143             }
3144             # ifdef USE_MD5
3145 0 0         if (hash_idx == PKCS1_MD5_ID)
3146             {
3147 0           psMd5Init(&md.md5);
3148 0           memset(mask, 0x0, 8);
3149 0           psMd5Update(&md.md5, mask, 8);
3150 0           psMd5Update(&md.md5, msghash, msghashlen);
3151 0           psMd5Update(&md.md5, DB + x, saltlen);
3152 0           psMd5Final(&md.md5, mask);
3153             }
3154             # endif /* USE_MD5 */
3155              
3156             # ifdef USE_SHA256
3157 0 0         if (hash_idx == PKCS1_SHA256_ID)
3158             {
3159 0           psSha256Init(&md.sha256);
3160 0           memset(mask, 0x0, 8);
3161 0           psSha256Update(&md.sha256, mask, 8);
3162 0           psSha256Update(&md.sha256, msghash, msghashlen);
3163 0           psSha256Update(&md.sha256, DB + x, saltlen);
3164 0           psSha256Final(&md.sha256, mask);
3165             }
3166             # endif
3167             # ifdef USE_SHA384
3168 0 0         if (hash_idx == PKCS1_SHA384_ID)
3169             {
3170 0           psSha384Init(&md.sha384);
3171 0           memset(mask, 0x0, 8);
3172 0           psSha384Update(&md.sha384, mask, 8);
3173 0           psSha384Update(&md.sha384, msghash, msghashlen);
3174 0           psSha384Update(&md.sha384, DB + x, saltlen);
3175 0           psSha384Final(&md.sha384, mask);
3176             }
3177             # endif
3178             # ifdef USE_SHA512
3179 0 0         if (hash_idx == PKCS1_SHA512_ID)
3180             {
3181 0           psSha512Init(&md.sha512);
3182 0           memset(mask, 0x0, 8);
3183 0           psSha512Update(&md.sha512, mask, 8);
3184 0           psSha512Update(&md.sha512, msghash, msghashlen);
3185 0           psSha512Update(&md.sha512, DB + x, saltlen);
3186 0           psSha512Final(&md.sha512, mask);
3187             }
3188             # endif
3189              
3190             /* mask == hash means valid signature */
3191 0 0         if (memcmp(mask, hash, hLen) == 0)
3192             {
3193 0           *res = 1;
3194             }
3195              
3196 0           err = PS_SUCCESS;
3197              
3198             LBL_ERR:
3199 0           psFree(hash, pool);
3200             LBL_SALT:
3201 0           psFree(salt, pool);
3202             LBL_MASK:
3203 0           psFree(mask, pool);
3204             LBL_DB:
3205 0           psFree(DB, pool);
3206 0           memset_s(&md, sizeof(psDigestContext_t), 0x0, sizeof(psDigestContext_t));
3207              
3208 0           return err;
3209             }
3210             #endif /* USE_PKCS1_PSS */
3211              
3212             /******************************************************************************/
3213              
3214             /******************************************************************************/
3215