Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of wolfSSL by
pkcs12.c
00001 /* pkcs12.c 00002 * 00003 * Copyright (C) 2006-2016 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <wolfssl/wolfcrypt/settings.h> 00028 00029 #if !defined(NO_ASN) && !defined(NO_PWDBASED) 00030 00031 #include <wolfssl/wolfcrypt/asn.h> 00032 #include <wolfssl/wolfcrypt/asn_public.h> 00033 #include <wolfssl/wolfcrypt/error-crypt.h> 00034 #include <wolfssl/wolfcrypt/hmac.h> 00035 #include <wolfssl/wolfcrypt/logging.h> 00036 #ifdef NO_INLINE 00037 #include <wolfssl/wolfcrypt/misc.h> 00038 #else 00039 #define WOLFSSL_MISC_INCLUDED 00040 #include <wolfcrypt/src/misc.c> 00041 #endif 00042 #include <wolfssl/wolfcrypt/pkcs12.h> 00043 #include <wolfssl/wolfcrypt/pwdbased.h> 00044 00045 00046 enum { 00047 WC_PKCS12_KeyBag = 667, 00048 WC_PKCS12_ShroudedKeyBag = 668, 00049 WC_PKCS12_CertBag = 669, 00050 WC_PKCS12_CertBag_Type1 = 675, 00051 WC_PKCS12_CrlBag = 670, 00052 WC_PKCS12_SecretBag = 671, 00053 WC_PKCS12_SafeContentsBag = 672, 00054 WC_PKCS12_DATA = 651, 00055 WC_PKCS12_ENCRYPTED_DATA = 656, 00056 }; 00057 00058 typedef struct ContentInfo { 00059 byte* data; 00060 struct ContentInfo* next; 00061 word32 encC; /* encryptedContent */ 00062 word32 dataSz; 00063 int type; /* DATA / encrypted / envelpoed */ 00064 } ContentInfo; 00065 00066 00067 typedef struct AuthenticatedSafe { 00068 ContentInfo* CI; 00069 byte* data; /* T contents.... */ 00070 word32 oid; /* encrypted or not */ 00071 word32 numCI; /* number of Content Info structs */ 00072 word32 dataSz; 00073 } AuthenticatedSafe; 00074 00075 00076 typedef struct MacData { 00077 byte* digest; 00078 byte* salt; 00079 word32 oid; 00080 word32 digestSz; 00081 word32 saltSz; 00082 int itt; /* number of itterations when creating HMAC key */ 00083 } MacData; 00084 00085 00086 struct WC_PKCS12 { 00087 void* heap; 00088 AuthenticatedSafe* safe; 00089 MacData* signData; 00090 word32 oid; /* DATA / Enveloped DATA ... */ 00091 }; 00092 00093 00094 /* for friendlyName, localKeyId .... */ 00095 typedef struct WC_PKCS12_ATTRIBUTE { 00096 byte* data; 00097 word32 oid; 00098 word32 dataSz; 00099 } WC_PKCS12_ATTRIBUTE; 00100 00101 00102 WC_PKCS12* wc_PKCS12_new(void) 00103 { 00104 WC_PKCS12* pkcs12 = (WC_PKCS12*)XMALLOC(sizeof(WC_PKCS12), 00105 NULL, DYNAMIC_TYPE_PKCS); 00106 if (pkcs12 == NULL) { 00107 WOLFSSL_MSG("Memory issue when creating WC_PKCS12 struct"); 00108 return NULL; 00109 } 00110 00111 XMEMSET(pkcs12, 0, sizeof(WC_PKCS12)); 00112 00113 return pkcs12; 00114 } 00115 00116 00117 static void freeSafe(AuthenticatedSafe* safe, void* heap) 00118 { 00119 int i; 00120 00121 if (safe == NULL) { 00122 return; 00123 } 00124 00125 /* free content info structs */ 00126 for (i = safe->numCI; i > 0; i--) { 00127 ContentInfo* ci = safe->CI; 00128 safe->CI = ci->next; 00129 XFREE(ci, heap, DYNAMIC_TYPE_PKCS); 00130 } 00131 if (safe->data != NULL) { 00132 XFREE(safe->data, heap, DYNAMIC_TYPE_PKCS); 00133 } 00134 XFREE(safe, heap, DYNAMIC_TYPE_PKCS); 00135 00136 (void)heap; 00137 } 00138 00139 00140 void wc_PKCS12_free(WC_PKCS12* pkcs12) 00141 { 00142 void* heap; 00143 00144 /* if null pointer is passed in do nothing */ 00145 if (pkcs12 == NULL) { 00146 WOLFSSL_MSG("Trying to free null WC_PKCS12 object"); 00147 return; 00148 } 00149 00150 heap = pkcs12->heap; 00151 if (pkcs12->safe != NULL) { 00152 freeSafe(pkcs12->safe, heap); 00153 } 00154 00155 /* free mac data */ 00156 if (pkcs12->signData != NULL) { 00157 if (pkcs12->signData->digest != NULL) { 00158 XFREE(pkcs12->signData->digest, heap, DYNAMIC_TYPE_PKCS); 00159 } 00160 if (pkcs12->signData->salt != NULL) { 00161 XFREE(pkcs12->signData->salt, heap, DYNAMIC_TYPE_PKCS); 00162 } 00163 XFREE(pkcs12->signData, heap, DYNAMIC_TYPE_PKCS); 00164 } 00165 00166 XFREE(pkcs12, NULL, DYNAMIC_TYPE_PKCS); 00167 pkcs12 = NULL; 00168 00169 (void)heap; 00170 } 00171 00172 00173 static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, 00174 word32* idx, int maxIdx) 00175 { 00176 AuthenticatedSafe* safe; 00177 word32 oid; 00178 word32 localIdx = *idx; 00179 int ret; 00180 int size = 0; 00181 00182 safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), pkcs12->heap, 00183 DYNAMIC_TYPE_PKCS); 00184 if (safe == NULL) { 00185 return MEMORY_E; 00186 } 00187 XMEMSET(safe, 0, sizeof(AuthenticatedSafe)); 00188 00189 ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, maxIdx); 00190 if (ret < 0) { 00191 WOLFSSL_LEAVE("Get object id failed", ret); 00192 freeSafe(safe, pkcs12->heap); 00193 return ASN_PARSE_E; 00194 } 00195 00196 safe->oid = oid; 00197 /* check tag, length */ 00198 if (input[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00199 WOLFSSL_MSG("Unexpected tag in PKCS12 DER"); 00200 freeSafe(safe, pkcs12->heap); 00201 return ASN_PARSE_E; 00202 } 00203 if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { 00204 freeSafe(safe, pkcs12->heap); 00205 return ret; 00206 } 00207 00208 switch (oid) { 00209 case WC_PKCS12_ENCRYPTED_DATA: 00210 WOLFSSL_MSG("Found PKCS12 OBJECT: ENCRYPTED DATA\n"); 00211 break; 00212 00213 case WC_PKCS12_DATA: 00214 WOLFSSL_MSG("Found PKCS12 OBJECT: DATA"); 00215 /* get octets holding contents */ 00216 if (input[localIdx++] != ASN_OCTET_STRING) { 00217 WOLFSSL_MSG("Wrong tag with content PKCS12 type DATA"); 00218 freeSafe(safe, pkcs12->heap); 00219 return ASN_PARSE_E; 00220 } 00221 if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { 00222 freeSafe(safe, pkcs12->heap); 00223 return ret; 00224 } 00225 00226 break; 00227 } 00228 00229 safe->dataSz = size; 00230 safe->data = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00231 if (safe->data == NULL) { 00232 freeSafe(safe, pkcs12->heap); 00233 return MEMORY_E; 00234 } 00235 XMEMCPY(safe->data, input + localIdx, size); 00236 *idx = localIdx; 00237 00238 /* an instance of AuthenticatedSafe is created from 00239 * ContentInfo's strung together in a SEQUENCE. Here we itterate 00240 * through the ContentInfo's and add them to our 00241 * AuthenticatedSafe struct */ 00242 localIdx = 0; 00243 input = safe->data; 00244 { 00245 int CISz; 00246 ret = GetSequence(input, &localIdx, &CISz, safe->dataSz); 00247 if (ret < 0) { 00248 freeSafe(safe, pkcs12->heap); 00249 return ASN_PARSE_E; 00250 } 00251 CISz += localIdx; 00252 while ((int)localIdx < CISz) { 00253 int curSz = 0; 00254 word32 curIdx; 00255 ContentInfo* ci = NULL; 00256 00257 #ifdef WOLFSSL_DEBUG_PKCS12 00258 printf("\t\tlooking for Content Info.... "); 00259 #endif 00260 00261 if ((ret = GetSequence(input, &localIdx, &curSz, safe->dataSz)) 00262 < 0) { 00263 freeSafe(safe, pkcs12->heap); 00264 return ret; 00265 } 00266 00267 if (curSz > CISz) { 00268 /* subset should not be larger than universe */ 00269 freeSafe(safe, pkcs12->heap); 00270 return ASN_PARSE_E; 00271 } 00272 00273 curIdx = localIdx; 00274 if ((ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, 00275 safe->dataSz)) < 0) { 00276 WOLFSSL_LEAVE("Get object id failed", ret); 00277 freeSafe(safe, pkcs12->heap); 00278 return ret; 00279 } 00280 00281 /* create new content info struct ... possible OID sanity check? */ 00282 ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), pkcs12->heap, 00283 DYNAMIC_TYPE_PKCS); 00284 if (ci == NULL) { 00285 freeSafe(safe, pkcs12->heap); 00286 return MEMORY_E; 00287 } 00288 00289 ci->type = oid; 00290 ci->dataSz = curSz - (localIdx-curIdx); 00291 ci->data = (byte*)input + localIdx; 00292 localIdx += ci->dataSz; 00293 00294 #ifdef WOLFSSL_DEBUG_PKCS12 00295 switch (oid) { 00296 case WC_PKCS12_ENCRYPTED_DATA: 00297 printf("CONTENT INFO: ENCRYPTED DATA, size = %d\n", ci->dataSz); 00298 break; 00299 00300 case WC_PKCS12_DATA: 00301 printf("CONTENT INFO: DATA, size = %d\n", ci->dataSz); 00302 break; 00303 default: 00304 printf("CONTENT INFO: UNKNOWN, size = %d\n", ci->dataSz); 00305 } 00306 #endif 00307 00308 /* insert to head of list */ 00309 ci->next = safe->CI; 00310 safe->CI = ci; 00311 safe->numCI += 1; 00312 } 00313 } 00314 00315 pkcs12->safe = safe; 00316 *idx += localIdx; 00317 00318 return 1; 00319 } 00320 00321 00322 /* optional mac data */ 00323 static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, 00324 word32 totalSz) 00325 { 00326 MacData* mac; 00327 word32 curIdx = *idx; 00328 word32 oid = 0; 00329 int size, ret; 00330 00331 00332 /* Digest Info : Sequence 00333 * DigestAlgorithmIdentifier 00334 * Digest 00335 */ 00336 if ((ret = GetSequence(mem, &curIdx, &size, totalSz)) <= 0) { 00337 WOLFSSL_MSG("Failed to get PKCS12 sequence"); 00338 return ret; 00339 } 00340 00341 #ifdef WOLFSSL_DEBUG_PKCS12 00342 printf("\t\tSEQUENCE: DigestInfo size = %d\n", size); 00343 #endif 00344 00345 mac = (MacData*)XMALLOC(sizeof(MacData), pkcs12->heap, DYNAMIC_TYPE_PKCS); 00346 if (mac == NULL) { 00347 return MEMORY_E; 00348 } 00349 XMEMSET(mac, 0, sizeof(MacData)); 00350 00351 /* DigestAlgorithmIdentifier */ 00352 if ((ret = GetAlgoId(mem, &curIdx, &oid, oidIgnoreType, totalSz)) < 0) { 00353 WOLFSSL_MSG("Failed to get PKCS12 sequence"); 00354 XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00355 return ret; 00356 } 00357 mac->oid = oid; 00358 00359 #ifdef WOLFSSL_DEBUG_PKCS12 00360 printf("\t\tALGO ID = %d\n", oid); 00361 #endif 00362 00363 /* Digest: should be octet type holding digest */ 00364 if (mem[curIdx++] != ASN_OCTET_STRING) { 00365 WOLFSSL_MSG("Failed to get digest"); 00366 XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00367 return ASN_PARSE_E; 00368 } 00369 00370 if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) { 00371 XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00372 return ret; 00373 } 00374 mac->digestSz = size; 00375 mac->digest = (byte*)XMALLOC(mac->digestSz, pkcs12->heap, 00376 DYNAMIC_TYPE_PKCS); 00377 if (mac->digest == NULL || mac->digestSz + curIdx > totalSz) { 00378 XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00379 return MEMORY_E; 00380 } 00381 XMEMCPY(mac->digest, mem + curIdx, mac->digestSz); 00382 #ifdef WOLFSSL_DEBUG_PKCS12 00383 { 00384 byte* p; 00385 for (printf("\t\tDigest = "), p = (byte*)mem+curIdx; 00386 p < (byte*)mem + curIdx + mac->digestSz; 00387 printf("%02X", *p), p++); 00388 printf(" : size = %d\n", mac->digestSz); 00389 } 00390 #endif 00391 curIdx += mac->digestSz; 00392 00393 /* get salt, should be octet string */ 00394 if (mem[curIdx++] != ASN_OCTET_STRING) { 00395 WOLFSSL_MSG("Failed to get salt"); 00396 XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00397 XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00398 return ASN_PARSE_E; 00399 } 00400 00401 if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) { 00402 XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00403 XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00404 return ret; 00405 } 00406 mac->saltSz = size; 00407 mac->salt = (byte*)XMALLOC(mac->saltSz, pkcs12->heap, 00408 DYNAMIC_TYPE_PKCS); 00409 if (mac->salt == NULL || mac->saltSz + curIdx > totalSz) { 00410 XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00411 XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00412 return MEMORY_E; 00413 } 00414 XMEMCPY(mac->salt, mem + curIdx, mac->saltSz); 00415 #ifdef WOLFSSL_DEBUG_PKCS12 00416 { 00417 byte* p; 00418 for (printf("\t\tSalt = "), p = (byte*)mem + curIdx; 00419 p < (byte*)mem + curIdx + mac->saltSz; 00420 printf("%02X", *p), p++); 00421 printf(" : size = %d\n", mac->saltSz); 00422 } 00423 #endif 00424 curIdx += mac->saltSz; 00425 00426 /* check for MAC itterations, default to 1 */ 00427 mac->itt = 1; 00428 if (curIdx < totalSz) { 00429 int number = 0; 00430 if ((ret = GetShortInt(mem, &curIdx, &number, totalSz)) >= 0) { 00431 /* found a itteration value */ 00432 mac->itt = number; 00433 } 00434 } 00435 00436 #ifdef WOLFSSL_DEBUG_PKCS12 00437 printf("\t\tITTERATIONS : %d\n", mac->itt); 00438 #endif 00439 00440 *idx = curIdx; 00441 pkcs12->signData = mac; 00442 00443 return 0; 00444 } 00445 00446 00447 /* check mac on pkcs12, pkcs12->mac has been sanity checked before entering * 00448 * returns the result of comparison, success is 0 */ 00449 static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz, 00450 const byte* psw, word32 pswSz) 00451 { 00452 Hmac hmac; 00453 MacData* mac; 00454 int ret, typeH, kLen; 00455 int idx = 0; 00456 int id = 3; /* value from RFC 7292 indicating key is used for MAC */ 00457 word32 i; 00458 byte digest[MAX_DIGEST_SIZE]; 00459 byte unicodePasswd[MAX_UNICODE_SZ]; 00460 byte key[MAX_KEY_SIZE]; 00461 00462 mac = pkcs12->signData; 00463 00464 #ifdef WOLFSSL_DEBUG_PKCS12 00465 printf("Verifying MAC with OID = %d\n", mac->oid); 00466 #endif 00467 00468 /* check if this builds digest size is too small */ 00469 if (mac->digestSz > MAX_DIGEST_SIZE) { 00470 WOLFSSL_MSG("PKCS12 max digest size too small"); 00471 return BAD_FUNC_ARG; 00472 } 00473 00474 /* unicode set up from asn.c */ 00475 if ( (pswSz * 2 + 2) > (int)sizeof(unicodePasswd)) { 00476 WOLFSSL_MSG("PKCS12 max unicode size too small"); 00477 return UNICODE_SIZE_E; 00478 } 00479 00480 for (i = 0; i < pswSz; i++) { 00481 unicodePasswd[idx++] = 0x00; 00482 unicodePasswd[idx++] = (byte)psw[i]; 00483 } 00484 /* add trailing NULL */ 00485 unicodePasswd[idx++] = 0x00; 00486 unicodePasswd[idx++] = 0x00; 00487 00488 /* get hash type used and resulting size of HMAC key */ 00489 switch (mac->oid) { 00490 #ifndef NO_SHA 00491 case SHAh: /* 88 */ 00492 typeH = SHA; 00493 kLen = SHA_DIGEST_SIZE; 00494 break; 00495 #endif 00496 00497 #ifndef NO_SHA256 00498 case SHA256h: /* 414 */ 00499 typeH = SHA256; 00500 kLen = SHA256_DIGEST_SIZE; 00501 break; 00502 #endif 00503 00504 #ifdef WOLFSSL_SHA384 00505 case SHA384h: /* 415 */ 00506 typeH = SHA384; 00507 kLen = SHA384_DIGEST_SIZE; 00508 break; 00509 #endif 00510 00511 #ifdef WOLFSSL_SHA512 00512 case SHA512h: /* 416 */ 00513 typeH = SHA512; 00514 kLen = SHA512_DIGEST_SIZE; 00515 break; 00516 #endif 00517 00518 default: /* May be SHA224 or was just not built in */ 00519 WOLFSSL_MSG("Unsupported hash used"); 00520 return BAD_FUNC_ARG; 00521 } 00522 00523 /* idx contains size of unicodePasswd */ 00524 if ((ret = wc_PKCS12_PBKDF_ex(key, unicodePasswd, idx, mac->salt, 00525 mac->saltSz, mac->itt, kLen, typeH, id, pkcs12->heap)) < 0) { 00526 return ret; 00527 } 00528 00529 /* now that key has been created use it to get HMAC hash on data */ 00530 if ((ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID)) != 0) { 00531 return ret; 00532 } 00533 ret = wc_HmacSetKey(&hmac, typeH, key, kLen); 00534 if (ret == 0) 00535 ret = wc_HmacUpdate(&hmac, data, dataSz); 00536 if (ret == 0) 00537 ret = wc_HmacFinal(&hmac, digest); 00538 wc_HmacFree(&hmac); 00539 00540 if (ret != 0) 00541 return ret; 00542 00543 #ifdef WOLFSSL_DEBUG_PKCS12 00544 { 00545 byte* p; 00546 for (printf("\t\tHash = "), p = (byte*)digest; 00547 p < (byte*)digest + mac->digestSz; 00548 printf("%02X", *p), p++); 00549 printf(" : size = %d\n", mac->digestSz); 00550 } 00551 #endif 00552 00553 return XMEMCMP(digest, mac->digest, mac->digestSz); 00554 } 00555 00556 00557 /* Convert DER format stored in der buffer to WC_PKCS12 struct 00558 * Puts the raw contents of Content Info into structure without completly 00559 * parsing or decoding. 00560 * der : pointer to der buffer holding PKCS12 00561 * derSz : size of der buffer 00562 * pkcs12 : non-null pkcs12 pointer 00563 */ 00564 int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12) 00565 { 00566 word32 idx = 0; 00567 word32 totalSz = 0; 00568 int ret; 00569 int size = 0; 00570 int version = 0; 00571 00572 WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio"); 00573 00574 if (der == NULL || pkcs12 == NULL) { 00575 return BAD_FUNC_ARG; 00576 } 00577 00578 totalSz = derSz; 00579 if ((ret = GetSequence(der, &idx, &size, totalSz)) <= 0) { 00580 WOLFSSL_MSG("Failed to get PKCS12 sequence"); 00581 return ret; 00582 } 00583 00584 /* get version */ 00585 if ((ret = GetMyVersion(der, &idx, &version, totalSz)) < 0) { 00586 return ret; 00587 } 00588 00589 #ifdef WOLFSSL_DEBUG_PKCS12 00590 printf("\nBEGIN: PKCS12 size = %d\n", totalSz); 00591 printf("version = %d\n", version); 00592 #endif 00593 00594 if (version != 3) { 00595 WOLFSSL_MSG("PKCS12 unsupported version!"); 00596 return ASN_VERSION_E; 00597 } 00598 00599 if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) { 00600 return ret; 00601 } 00602 00603 #ifdef WOLFSSL_DEBUG_PKCS12 00604 printf("\tSEQUENCE: AuthenticatedSafe size = %d\n", size); 00605 #endif 00606 00607 if ((ret = GetSafeContent(pkcs12, der, &idx, size + idx)) < 0) { 00608 WOLFSSL_MSG("GetSafeContent error"); 00609 return ret; 00610 } 00611 00612 /* if more buffer left check for MAC data */ 00613 if (idx < totalSz) { 00614 if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) { 00615 WOLFSSL_MSG("Ignoring unknown data at end of PKCS12 DER buffer"); 00616 } 00617 else { 00618 #ifdef WOLFSSL_DEBUG_PKCS12 00619 printf("\tSEQUENCE: Signature size = %d\n", size); 00620 #endif 00621 00622 if ((ret = GetSignData(pkcs12, der, &idx, totalSz)) < 0) { 00623 return ASN_PARSE_E; 00624 } 00625 } 00626 } 00627 00628 #ifdef WOLFSSL_DEBUG_PKCS12 00629 printf("END: PKCS12\n"); 00630 #endif 00631 00632 return 1; 00633 } 00634 00635 00636 /* helper function to free WC_DerCertList */ 00637 static void freeCertList(WC_DerCertList* list, void* heap) { 00638 WC_DerCertList* current; 00639 00640 if (list == NULL) { 00641 return; 00642 } 00643 00644 current = list; 00645 while(current != NULL) { 00646 WC_DerCertList* next = current->next; 00647 if (current->buffer != NULL) { 00648 XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); 00649 } 00650 XFREE(current, heap, DYNAMIC_TYPE_PKCS); 00651 current = next; 00652 } 00653 00654 (void)heap; 00655 } 00656 00657 00658 static void freeBuffers(byte* a, byte* b, void* heap) 00659 { 00660 if (a != NULL) { 00661 XFREE(a, heap, DYNAMIC_TYPE_PKCS); 00662 } 00663 if (b != NULL) { 00664 XFREE(b, heap, DYNAMIC_TYPE_PKCS); 00665 } 00666 (void)heap; 00667 } 00668 00669 00670 /* return 1 on success and 0 on failure. 00671 * By side effect returns private key, cert, and optionally ca. 00672 * Parses and decodes the parts of PKCS12 00673 * 00674 * NOTE: can parse with USER RSA enabled but may return cert that is not the 00675 * pair for the key when using RSA key pairs. 00676 * 00677 * pkcs12 : non-null WC_PKCS12 struct 00678 * psw : password to use for PKCS12 decode 00679 * pkey : Private key returned 00680 * cert : x509 cert returned 00681 * ca : optional ca returned 00682 */ 00683 int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, 00684 byte** pkey, word32* pkeySz, byte** cert, word32* certSz, 00685 WC_DerCertList** ca) 00686 { 00687 ContentInfo* ci = NULL; 00688 WC_DerCertList* certList = NULL; 00689 byte* buf = NULL; 00690 word32 i, oid; 00691 int ret, pswSz; 00692 00693 WOLFSSL_ENTER("wc_PKCS12_parse"); 00694 00695 if (pkcs12 == NULL || psw == NULL || cert == NULL || certSz == NULL || 00696 pkey == NULL || pkeySz == NULL) { 00697 return BAD_FUNC_ARG; 00698 } 00699 pswSz = (int)XSTRLEN(psw); 00700 *cert = NULL; 00701 *pkey = NULL; 00702 if (ca != NULL) { 00703 *ca = NULL; 00704 } 00705 00706 /* if there is sign data then verify the MAC */ 00707 if (pkcs12->signData != NULL ) { 00708 if ((ret = wc_PKCS12_verify(pkcs12, pkcs12->safe->data, 00709 pkcs12->safe->dataSz, (byte*)psw, pswSz)) != 0) { 00710 WOLFSSL_MSG("PKCS12 Bad MAC on verify"); 00711 WOLFSSL_LEAVE("wc_PKCS12_parse verify ", ret); 00712 return MAC_CMP_FAILED_E; 00713 } 00714 } 00715 00716 if (pkcs12->safe == NULL) { 00717 WOLFSSL_MSG("No PKCS12 safes to parse"); 00718 return BAD_FUNC_ARG; 00719 } 00720 00721 /* Decode content infos */ 00722 ci = pkcs12->safe->CI; 00723 for (i = 0; i < pkcs12->safe->numCI; i++) { 00724 byte* data; 00725 word32 idx = 0; 00726 int size, totalSz; 00727 00728 if (ci->type == WC_PKCS12_ENCRYPTED_DATA) { 00729 int number; 00730 00731 WOLFSSL_MSG("Decrypting PKCS12 Content Info Container"); 00732 data = ci->data; 00733 if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00734 freeBuffers(*pkey, buf, pkcs12->heap); 00735 freeCertList(certList, pkcs12->heap); 00736 return ASN_PARSE_E; 00737 } 00738 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { 00739 freeBuffers(*pkey, buf, pkcs12->heap); 00740 freeCertList(certList, pkcs12->heap); 00741 return ret; 00742 } 00743 00744 if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) { 00745 freeBuffers(*pkey, buf, pkcs12->heap); 00746 freeCertList(certList, pkcs12->heap); 00747 return ret; 00748 } 00749 00750 if ((ret = GetShortInt(data, &idx, &number, ci->dataSz)) < 0) { 00751 freeBuffers(*pkey, buf, pkcs12->heap); 00752 freeCertList(certList, pkcs12->heap); 00753 return ret; 00754 } 00755 00756 if (number != 0) { 00757 WOLFSSL_MSG("Expecting 0 for Integer with Encrypted PKCS12"); 00758 } 00759 00760 if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) { 00761 freeBuffers(*pkey, buf, pkcs12->heap); 00762 freeCertList(certList, pkcs12->heap); 00763 return ret; 00764 } 00765 00766 ret = GetObjectId(data, &idx, &oid, oidIgnoreType, ci->dataSz); 00767 if (ret < 0 || oid != WC_PKCS12_DATA) { 00768 WOLFSSL_MSG("Not PKCS12 DATA object or get object parse error"); 00769 freeBuffers(*pkey, buf, pkcs12->heap); 00770 freeCertList(certList, pkcs12->heap); 00771 return ASN_PARSE_E; 00772 } 00773 00774 /* decrypted content overwrites input buffer */ 00775 size = ci->dataSz - idx; 00776 buf = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00777 if (buf == NULL) { 00778 freeBuffers(*pkey, buf, pkcs12->heap); 00779 freeCertList(certList, pkcs12->heap); 00780 return MEMORY_E; 00781 } 00782 XMEMCPY(buf, data + idx, size); 00783 00784 if ((ret = DecryptContent(buf, size, psw, pswSz)) < 0) { 00785 freeBuffers(*pkey, buf, pkcs12->heap); 00786 freeCertList(certList, pkcs12->heap); 00787 WOLFSSL_MSG("Decryption failed, algorithm not compiled in?"); 00788 return ret; 00789 } 00790 00791 data = buf; 00792 idx = 0; 00793 #ifdef WOLFSSL_DEBUG_PKCS12 00794 { 00795 byte* p; 00796 for (printf("\tData = "), p = (byte*)buf; 00797 p < (byte*)buf + size; 00798 printf("%02X", *p), p++); 00799 printf("\n"); 00800 } 00801 #endif 00802 } 00803 else { /* type DATA */ 00804 WOLFSSL_MSG("Parsing PKCS12 DATA Content Info Container"); 00805 data = ci->data; 00806 if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00807 freeBuffers(*pkey, buf, pkcs12->heap); 00808 freeCertList(certList, pkcs12->heap); 00809 return ASN_PARSE_E; 00810 } 00811 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { 00812 freeBuffers(*pkey, buf, pkcs12->heap); 00813 freeCertList(certList, pkcs12->heap); 00814 return ret; 00815 } 00816 if (data[idx++] != ASN_OCTET_STRING) { 00817 freeBuffers(*pkey, buf, pkcs12->heap); 00818 freeCertList(certList, pkcs12->heap); 00819 return ASN_PARSE_E; 00820 } 00821 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { 00822 freeBuffers(*pkey, buf, pkcs12->heap); 00823 freeCertList(certList, pkcs12->heap); 00824 return ret; 00825 } 00826 00827 } 00828 00829 /* parse through bags in ContentInfo */ 00830 if ((ret = GetSequence(data, &idx, &totalSz, ci->dataSz)) < 0) { 00831 freeBuffers(*pkey, buf, pkcs12->heap); 00832 freeCertList(certList, pkcs12->heap); 00833 return ret; 00834 } 00835 totalSz += idx; 00836 00837 while ((int)idx < totalSz) { 00838 int bagSz; 00839 if ((ret = GetSequence(data, &idx, &bagSz, ci->dataSz)) < 0) { 00840 freeBuffers(*pkey, buf, pkcs12->heap); 00841 freeCertList(certList, pkcs12->heap); 00842 return ret; 00843 } 00844 bagSz += idx; 00845 00846 if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType, 00847 ci->dataSz)) < 0) { 00848 freeBuffers(*pkey, buf, pkcs12->heap); 00849 freeCertList(certList, pkcs12->heap); 00850 return ret; 00851 } 00852 00853 switch (oid) { 00854 case WC_PKCS12_KeyBag: /* 667 */ 00855 WOLFSSL_MSG("PKCS12 Key Bag found"); 00856 if (data[idx++] != 00857 (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00858 freeBuffers(*pkey, buf, pkcs12->heap); 00859 freeCertList(certList, pkcs12->heap); 00860 return ASN_PARSE_E; 00861 } 00862 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { 00863 freeBuffers(*pkey, buf, pkcs12->heap); 00864 freeCertList(certList, pkcs12->heap); 00865 return ASN_PARSE_E; 00866 } 00867 if (*pkey == NULL) { 00868 *pkey = (byte*)XMALLOC(size, pkcs12->heap, 00869 DYNAMIC_TYPE_PKCS); 00870 if (*pkey == NULL) { 00871 freeBuffers(*pkey, buf, pkcs12->heap); 00872 freeCertList(certList, pkcs12->heap); 00873 return MEMORY_E; 00874 } 00875 XMEMCPY(*pkey, data + idx, size); 00876 *pkeySz = ToTraditional(*pkey, size); 00877 } 00878 #ifdef WOLFSSL_DEBUG_PKCS12 00879 { 00880 byte* p; 00881 for (printf("\tKey = "), p = (byte*)*pkey; 00882 p < (byte*)*pkey + size; 00883 printf("%02X", *p), p++); 00884 printf("\n"); 00885 } 00886 #endif 00887 idx += size; 00888 break; 00889 00890 case WC_PKCS12_ShroudedKeyBag: /* 668 */ 00891 { 00892 byte* k; 00893 WOLFSSL_MSG("PKCS12 Shrouded Key Bag found"); 00894 if (data[idx++] != 00895 (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00896 freeBuffers(*pkey, buf, pkcs12->heap); 00897 freeCertList(certList, pkcs12->heap); 00898 return ASN_PARSE_E; 00899 } 00900 if ((ret = GetLength(data, &idx, &size, 00901 ci->dataSz)) < 0) { 00902 freeBuffers(*pkey, buf, pkcs12->heap); 00903 freeCertList(certList, pkcs12->heap); 00904 return ASN_PARSE_E; 00905 } 00906 00907 k = (byte*)XMALLOC(size, pkcs12->heap, 00908 DYNAMIC_TYPE_PKCS); 00909 if (k == NULL) { 00910 freeBuffers(*pkey, buf, pkcs12->heap); 00911 freeCertList(certList, pkcs12->heap); 00912 return MEMORY_E; 00913 } 00914 XMEMCPY(k, data + idx, size); 00915 00916 /* overwrites input, be warned */ 00917 if ((ret = ToTraditionalEnc(k, size, psw, pswSz)) < 0) { 00918 freeBuffers(k, NULL, pkcs12->heap); 00919 freeBuffers(*pkey, buf, pkcs12->heap); 00920 freeCertList(certList, pkcs12->heap); 00921 return ret; 00922 } 00923 00924 if (ret < size) { 00925 /* shrink key buffer */ 00926 k = (byte*)XREALLOC(k, ret, pkcs12->heap, 00927 DYNAMIC_TYPE_PKCS); 00928 if (k == NULL) { 00929 freeBuffers(*pkey, buf, pkcs12->heap); 00930 freeCertList(certList, pkcs12->heap); 00931 return MEMORY_E; 00932 } 00933 } 00934 size = ret; 00935 00936 if (*pkey == NULL) { 00937 *pkey = k; 00938 *pkeySz = size; 00939 } 00940 else { /* only expecting one key */ 00941 freeBuffers(k, NULL, pkcs12->heap); 00942 } 00943 idx += size; 00944 00945 #ifdef WOLFSSL_DEBUG_PKCS12 00946 { 00947 byte* p; 00948 for (printf("\tKey = "), p = (byte*)k; 00949 p < (byte*)k + ret; 00950 printf("%02X", *p), p++); 00951 printf("\n"); 00952 } 00953 #endif 00954 } 00955 break; 00956 00957 case WC_PKCS12_CertBag: /* 669 */ 00958 { 00959 WC_DerCertList* node; 00960 WOLFSSL_MSG("PKCS12 Cert Bag found"); 00961 if (data[idx++] != 00962 (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00963 freeBuffers(*pkey, buf, pkcs12->heap); 00964 freeCertList(certList, pkcs12->heap); 00965 return ASN_PARSE_E; 00966 } 00967 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { 00968 freeBuffers(*pkey, buf, pkcs12->heap); 00969 freeCertList(certList, pkcs12->heap); 00970 return ret; 00971 } 00972 00973 /* get cert bag type */ 00974 if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) <0) { 00975 freeBuffers(*pkey, buf, pkcs12->heap); 00976 freeCertList(certList, pkcs12->heap); 00977 return ret; 00978 } 00979 00980 if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType, 00981 ci->dataSz)) < 0) { 00982 freeBuffers(*pkey, buf, pkcs12->heap); 00983 freeCertList(certList, pkcs12->heap); 00984 return ret; 00985 } 00986 00987 switch (oid) { 00988 case WC_PKCS12_CertBag_Type1: /* 675 */ 00989 /* type 1 */ 00990 WOLFSSL_MSG("PKCS12 cert bag type 1"); 00991 if (data[idx++] != 00992 (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00993 freeBuffers(*pkey, buf, pkcs12->heap); 00994 freeCertList(certList, pkcs12->heap); 00995 return ASN_PARSE_E; 00996 } 00997 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) 00998 <= 0) { 00999 freeBuffers(*pkey, buf, pkcs12->heap); 01000 freeCertList(certList, pkcs12->heap); 01001 return ret; 01002 } 01003 if (data[idx++] != ASN_OCTET_STRING) { 01004 freeBuffers(*pkey, buf, pkcs12->heap); 01005 freeCertList(certList, pkcs12->heap); 01006 return ASN_PARSE_E; 01007 } 01008 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) 01009 < 0) { 01010 freeBuffers(*pkey, buf, pkcs12->heap); 01011 freeCertList(certList, pkcs12->heap); 01012 return ret; 01013 } 01014 break; 01015 default: 01016 WOLFSSL_MSG("Unknown PKCS12 cert bag type"); 01017 } 01018 01019 if (size + idx > (word32)bagSz) { 01020 freeBuffers(*pkey, buf, pkcs12->heap); 01021 freeCertList(certList, pkcs12->heap); 01022 return ASN_PARSE_E; 01023 } 01024 01025 /* list to hold all certs found */ 01026 node = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), 01027 pkcs12->heap, DYNAMIC_TYPE_PKCS); 01028 if (node == NULL) { 01029 freeBuffers(*pkey, buf, pkcs12->heap); 01030 freeCertList(certList, pkcs12->heap); 01031 return MEMORY_E; 01032 } 01033 XMEMSET(node, 0, sizeof(WC_DerCertList)); 01034 01035 node->buffer = (byte*)XMALLOC(size, pkcs12->heap, 01036 DYNAMIC_TYPE_PKCS); 01037 if (node->buffer == NULL) { 01038 XFREE(node, pkcs12->heap, DYNAMIC_TYPE_PKCS); 01039 freeBuffers(*pkey, buf, pkcs12->heap); 01040 freeCertList(certList, pkcs12->heap); 01041 return MEMORY_E; 01042 } 01043 XMEMCPY(node->buffer, data + idx, size); 01044 node->bufferSz = size; 01045 01046 /* put the new node into the list */ 01047 if (certList != NULL) { 01048 WOLFSSL_MSG("Pushing new cert onto stack"); 01049 node->next = certList; 01050 certList = node; 01051 } 01052 else { 01053 certList = node; 01054 } 01055 01056 /* on to next */ 01057 idx += size; 01058 } 01059 break; 01060 01061 case WC_PKCS12_CrlBag: /* 670 */ 01062 WOLFSSL_MSG("PKCS12 CRL BAG not yet supported"); 01063 break; 01064 01065 case WC_PKCS12_SecretBag: /* 671 */ 01066 WOLFSSL_MSG("PKCS12 Secret BAG not yet supported"); 01067 break; 01068 01069 case WC_PKCS12_SafeContentsBag: /* 672 */ 01070 WOLFSSL_MSG("PKCS12 Safe Contents BAG not yet supported"); 01071 break; 01072 01073 default: 01074 WOLFSSL_MSG("Unknown PKCS12 BAG type found"); 01075 } 01076 01077 /* Attribute, unknown bag or unsupported */ 01078 if ((int)idx < bagSz) { 01079 idx = bagSz; /* skip for now */ 01080 } 01081 } 01082 01083 /* free temporary buffer */ 01084 if (buf != NULL) { 01085 XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS); 01086 buf = NULL; 01087 } 01088 ci = ci->next; 01089 WOLFSSL_MSG("Done Parsing PKCS12 Content Info Container"); 01090 } 01091 01092 /* check if key pair, remove from list */ 01093 { 01094 WC_DerCertList* current = certList; 01095 WC_DerCertList* previous = NULL; 01096 01097 if (*pkey != NULL) { 01098 01099 while (current != NULL) { 01100 DecodedCert DeCert; 01101 InitDecodedCert(&DeCert, current->buffer, current->bufferSz, 01102 pkcs12->heap); 01103 if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) { 01104 if (wc_CheckPrivateKey(*pkey, *pkeySz, &DeCert) == 1) { 01105 WOLFSSL_MSG("Key Pair found"); 01106 *cert = current->buffer; 01107 *certSz = current->bufferSz; 01108 01109 if (previous == NULL) { 01110 certList = current->next; 01111 } 01112 else { 01113 previous->next = current->next; 01114 } 01115 FreeDecodedCert(&DeCert); 01116 XFREE(current, pkcs12->heap, DYNAMIC_TYPE_PKCS); 01117 break; 01118 } 01119 } 01120 01121 FreeDecodedCert(&DeCert); 01122 previous = current; 01123 current = current->next; 01124 } 01125 01126 } 01127 } 01128 01129 if (ca != NULL) { 01130 *ca = certList; 01131 } 01132 else { 01133 /* free list, not wanted */ 01134 freeCertList(certList, pkcs12->heap); 01135 } 01136 01137 return 1; 01138 } 01139 01140 01141 /* if using a specific memory heap */ 01142 int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap) 01143 { 01144 if (pkcs12 == NULL) { 01145 return BAD_FUNC_ARG; 01146 } 01147 pkcs12->heap = heap; 01148 01149 return 0; 01150 } 01151 01152 01153 /* getter for heap */ 01154 void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12) 01155 { 01156 if (pkcs12 == NULL) { 01157 return NULL; 01158 } 01159 01160 return pkcs12->heap; 01161 } 01162 01163 #endif /* !defined(NO_ASN) && !defined(NO_PWDBASED) */ 01164 01165
Generated on Tue Jul 12 2022 23:30:58 by
1.7.2
