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.
pkcs12.c
00001 /* pkcs12.c 00002 * 00003 * Copyright (C) 2006-2017 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 <wolfcrypt/settings.h> 00028 00029 #if !defined(NO_ASN) && !defined(NO_PWDBASED) 00030 00031 #include <wolfcrypt/asn.h> 00032 #include <wolfcrypt/asn_public.h> 00033 #include <wolfcrypt/error-crypt.h> 00034 #include <wolfcrypt/hmac.h> 00035 #include <wolfcrypt/logging.h> 00036 #ifdef NO_INLINE 00037 #include <wolfcrypt/misc.h> 00038 #else 00039 #define WOLFSSL_MISC_INCLUDED 00040 #include <wolfcrypt/src/misc.c> 00041 #endif 00042 #include <wolfcrypt/pkcs12.h> 00043 #include <wolfcrypt/pwdbased.h> 00044 #include <wolfcrypt/hash.h> 00045 00046 00047 #define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } 00048 00049 enum { 00050 WC_PKCS12_KeyBag = 667, 00051 WC_PKCS12_ShroudedKeyBag = 668, 00052 WC_PKCS12_CertBag = 669, 00053 WC_PKCS12_CertBag_Type1 = 675, 00054 WC_PKCS12_CrlBag = 670, 00055 WC_PKCS12_SecretBag = 671, 00056 WC_PKCS12_SafeContentsBag = 672, 00057 WC_PKCS12_DATA = 651, 00058 WC_PKCS12_ENCRYPTED_DATA = 656, 00059 00060 WC_PKCS12_DATA_OBJ_SZ = 11, 00061 }; 00062 00063 /* static const byte WC_PKCS12_ENCRYPTED_OID[] = 00064 {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06}; */ 00065 static const byte WC_PKCS12_DATA_OID[] = 00066 {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01}; 00067 static const byte WC_PKCS12_CertBag_Type1_OID[] = 00068 {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x16, 0x01}; 00069 static const byte WC_PKCS12_CertBag_OID[] = 00070 {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x03}; 00071 static const byte WC_PKCS12_KeyBag_OID[] = 00072 {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x01}; 00073 static const byte WC_PKCS12_ShroudedKeyBag_OID[] = 00074 {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x02}; 00075 00076 00077 typedef struct ContentInfo { 00078 byte* data; 00079 struct ContentInfo* next; 00080 word32 encC; /* encryptedContent */ 00081 word32 dataSz; 00082 int type; /* DATA / encrypted / envelpoed */ 00083 } ContentInfo; 00084 00085 00086 typedef struct AuthenticatedSafe { 00087 ContentInfo* CI; 00088 byte* data; /* T contents.... */ 00089 word32 oid; /* encrypted or not */ 00090 word32 numCI; /* number of Content Info structs */ 00091 word32 dataSz; 00092 } AuthenticatedSafe; 00093 00094 00095 typedef struct MacData { 00096 byte* digest; 00097 byte* salt; 00098 word32 oid; 00099 word32 digestSz; 00100 word32 saltSz; 00101 int itt; /* number of itterations when creating HMAC key */ 00102 } MacData; 00103 00104 00105 struct WC_PKCS12 { 00106 void* heap; 00107 AuthenticatedSafe* safe; 00108 MacData* signData; 00109 word32 oid; /* DATA / Enveloped DATA ... */ 00110 }; 00111 00112 00113 /* for friendlyName, localKeyId .... */ 00114 typedef struct WC_PKCS12_ATTRIBUTE { 00115 byte* data; 00116 word32 oid; 00117 word32 dataSz; 00118 } WC_PKCS12_ATTRIBUTE; 00119 00120 00121 WC_PKCS12* wc_PKCS12_new(void) 00122 { 00123 WC_PKCS12* pkcs12 = (WC_PKCS12*)XMALLOC(sizeof(WC_PKCS12), 00124 NULL, DYNAMIC_TYPE_PKCS); 00125 if (pkcs12 == NULL) { 00126 WOLFSSL_MSG("Memory issue when creating WC_PKCS12 struct"); 00127 return NULL; 00128 } 00129 00130 XMEMSET(pkcs12, 0, sizeof(WC_PKCS12)); 00131 00132 return pkcs12; 00133 } 00134 00135 00136 static void freeSafe(AuthenticatedSafe* safe, void* heap) 00137 { 00138 int i; 00139 00140 if (safe == NULL) { 00141 return; 00142 } 00143 00144 /* free content info structs */ 00145 for (i = safe->numCI; i > 0; i--) { 00146 ContentInfo* ci = safe->CI; 00147 safe->CI = ci->next; 00148 XFREE(ci, heap, DYNAMIC_TYPE_PKCS); 00149 } 00150 if (safe->data != NULL) { 00151 XFREE(safe->data, heap, DYNAMIC_TYPE_PKCS); 00152 } 00153 XFREE(safe, heap, DYNAMIC_TYPE_PKCS); 00154 00155 (void)heap; 00156 } 00157 00158 00159 void wc_PKCS12_free(WC_PKCS12* pkcs12) 00160 { 00161 void* heap; 00162 00163 /* if null pointer is passed in do nothing */ 00164 if (pkcs12 == NULL) { 00165 WOLFSSL_MSG("Trying to free null WC_PKCS12 object"); 00166 return; 00167 } 00168 00169 heap = pkcs12->heap; 00170 if (pkcs12->safe != NULL) { 00171 freeSafe(pkcs12->safe, heap); 00172 } 00173 00174 /* free mac data */ 00175 if (pkcs12->signData != NULL) { 00176 if (pkcs12->signData->digest != NULL) { 00177 XFREE(pkcs12->signData->digest, heap, DYNAMIC_TYPE_DIGEST); 00178 pkcs12->signData->digest = NULL; 00179 } 00180 if (pkcs12->signData->salt != NULL) { 00181 XFREE(pkcs12->signData->salt, heap, DYNAMIC_TYPE_SALT); 00182 pkcs12->signData->salt = NULL; 00183 } 00184 XFREE(pkcs12->signData, heap, DYNAMIC_TYPE_PKCS); 00185 pkcs12->signData = NULL; 00186 } 00187 00188 XFREE(pkcs12, NULL, DYNAMIC_TYPE_PKCS); 00189 pkcs12 = NULL; 00190 } 00191 00192 00193 static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, 00194 word32* idx, int maxIdx) 00195 { 00196 AuthenticatedSafe* safe; 00197 word32 oid; 00198 word32 localIdx = *idx; 00199 int ret; 00200 int size = 0; 00201 00202 safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), pkcs12->heap, 00203 DYNAMIC_TYPE_PKCS); 00204 if (safe == NULL) { 00205 return MEMORY_E; 00206 } 00207 XMEMSET(safe, 0, sizeof(AuthenticatedSafe)); 00208 00209 ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, maxIdx); 00210 if (ret < 0) { 00211 WOLFSSL_LEAVE("Get object id failed", ret); 00212 freeSafe(safe, pkcs12->heap); 00213 return ASN_PARSE_E; 00214 } 00215 00216 safe->oid = oid; 00217 /* check tag, length */ 00218 if (input[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00219 WOLFSSL_MSG("Unexpected tag in PKCS12 DER"); 00220 freeSafe(safe, pkcs12->heap); 00221 return ASN_PARSE_E; 00222 } 00223 if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { 00224 freeSafe(safe, pkcs12->heap); 00225 return ret; 00226 } 00227 00228 switch (oid) { 00229 case WC_PKCS12_ENCRYPTED_DATA: 00230 WOLFSSL_MSG("Found PKCS12 OBJECT: ENCRYPTED DATA\n"); 00231 break; 00232 00233 case WC_PKCS12_DATA: 00234 WOLFSSL_MSG("Found PKCS12 OBJECT: DATA"); 00235 /* get octets holding contents */ 00236 if (input[localIdx++] != ASN_OCTET_STRING) { 00237 WOLFSSL_MSG("Wrong tag with content PKCS12 type DATA"); 00238 freeSafe(safe, pkcs12->heap); 00239 return ASN_PARSE_E; 00240 } 00241 if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { 00242 freeSafe(safe, pkcs12->heap); 00243 return ret; 00244 } 00245 00246 break; 00247 } 00248 00249 safe->dataSz = size; 00250 safe->data = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00251 if (safe->data == NULL) { 00252 freeSafe(safe, pkcs12->heap); 00253 return MEMORY_E; 00254 } 00255 XMEMCPY(safe->data, input + localIdx, size); 00256 *idx = localIdx; 00257 00258 /* an instance of AuthenticatedSafe is created from 00259 * ContentInfo's strung together in a SEQUENCE. Here we itterate 00260 * through the ContentInfo's and add them to our 00261 * AuthenticatedSafe struct */ 00262 localIdx = 0; 00263 input = safe->data; 00264 { 00265 int CISz; 00266 ret = GetSequence(input, &localIdx, &CISz, safe->dataSz); 00267 if (ret < 0) { 00268 freeSafe(safe, pkcs12->heap); 00269 return ASN_PARSE_E; 00270 } 00271 CISz += localIdx; 00272 while ((int)localIdx < CISz) { 00273 int curSz = 0; 00274 word32 curIdx; 00275 ContentInfo* ci = NULL; 00276 00277 #ifdef WOLFSSL_DEBUG_PKCS12 00278 printf("\t\tlooking for Content Info.... "); 00279 #endif 00280 00281 if ((ret = GetSequence(input, &localIdx, &curSz, safe->dataSz)) 00282 < 0) { 00283 freeSafe(safe, pkcs12->heap); 00284 return ret; 00285 } 00286 00287 if (curSz > CISz) { 00288 /* subset should not be larger than universe */ 00289 freeSafe(safe, pkcs12->heap); 00290 return ASN_PARSE_E; 00291 } 00292 00293 curIdx = localIdx; 00294 if ((ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, 00295 safe->dataSz)) < 0) { 00296 WOLFSSL_LEAVE("Get object id failed", ret); 00297 freeSafe(safe, pkcs12->heap); 00298 return ret; 00299 } 00300 00301 /* create new content info struct ... possible OID sanity check? */ 00302 ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), pkcs12->heap, 00303 DYNAMIC_TYPE_PKCS); 00304 if (ci == NULL) { 00305 freeSafe(safe, pkcs12->heap); 00306 return MEMORY_E; 00307 } 00308 00309 ci->type = oid; 00310 ci->dataSz = curSz - (localIdx-curIdx); 00311 ci->data = (byte*)input + localIdx; 00312 localIdx += ci->dataSz; 00313 00314 #ifdef WOLFSSL_DEBUG_PKCS12 00315 switch (oid) { 00316 case WC_PKCS12_ENCRYPTED_DATA: 00317 printf("CONTENT INFO: ENCRYPTED DATA, size = %d\n", ci->dataSz); 00318 break; 00319 00320 case WC_PKCS12_DATA: 00321 printf("CONTENT INFO: DATA, size = %d\n", ci->dataSz); 00322 break; 00323 default: 00324 printf("CONTENT INFO: UNKNOWN, size = %d\n", ci->dataSz); 00325 } 00326 #endif 00327 00328 /* insert to head of list */ 00329 ci->next = safe->CI; 00330 safe->CI = ci; 00331 safe->numCI += 1; 00332 } 00333 } 00334 00335 pkcs12->safe = safe; 00336 *idx += localIdx; 00337 00338 return ret; 00339 } 00340 00341 00342 /* optional mac data */ 00343 static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, 00344 word32 totalSz) 00345 { 00346 MacData* mac; 00347 word32 curIdx = *idx; 00348 word32 oid = 0; 00349 int size, ret; 00350 00351 /* Digest Info : Sequence 00352 * DigestAlgorithmIdentifier 00353 * Digest 00354 */ 00355 if ((ret = GetSequence(mem, &curIdx, &size, totalSz)) <= 0) { 00356 WOLFSSL_MSG("Failed to get PKCS12 sequence"); 00357 return ret; 00358 } 00359 00360 #ifdef WOLFSSL_DEBUG_PKCS12 00361 printf("\t\tSEQUENCE: DigestInfo size = %d\n", size); 00362 #endif 00363 00364 mac = (MacData*)XMALLOC(sizeof(MacData), pkcs12->heap, DYNAMIC_TYPE_PKCS); 00365 if (mac == NULL) { 00366 return MEMORY_E; 00367 } 00368 XMEMSET(mac, 0, sizeof(MacData)); 00369 00370 /* DigestAlgorithmIdentifier */ 00371 if ((ret = GetAlgoId(mem, &curIdx, &oid, oidIgnoreType, totalSz)) < 0) { 00372 WOLFSSL_MSG("Failed to get PKCS12 sequence"); 00373 XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00374 return ret; 00375 } 00376 mac->oid = oid; 00377 00378 #ifdef WOLFSSL_DEBUG_PKCS12 00379 printf("\t\tALGO ID = %d\n", oid); 00380 #endif 00381 00382 /* Digest: should be octet type holding digest */ 00383 if (mem[curIdx++] != ASN_OCTET_STRING) { 00384 WOLFSSL_MSG("Failed to get digest"); 00385 XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00386 return ASN_PARSE_E; 00387 } 00388 00389 if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) { 00390 XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00391 return ret; 00392 } 00393 mac->digestSz = size; 00394 mac->digest = (byte*)XMALLOC(mac->digestSz, pkcs12->heap, 00395 DYNAMIC_TYPE_DIGEST); 00396 if (mac->digest == NULL || mac->digestSz + curIdx > totalSz) { 00397 ERROR_OUT(MEMORY_E, exit_gsd); 00398 } 00399 XMEMCPY(mac->digest, mem + curIdx, mac->digestSz); 00400 00401 #ifdef WOLFSSL_DEBUG_PKCS12 00402 { 00403 byte* p; 00404 for (printf("\t\tDigest = "), p = (byte*)mem+curIdx; 00405 p < (byte*)mem + curIdx + mac->digestSz; 00406 printf("%02X", *p), p++); 00407 printf(" : size = %d\n", mac->digestSz); 00408 } 00409 #endif 00410 00411 curIdx += mac->digestSz; 00412 00413 /* get salt, should be octet string */ 00414 if (mem[curIdx++] != ASN_OCTET_STRING) { 00415 WOLFSSL_MSG("Failed to get salt"); 00416 ERROR_OUT(ASN_PARSE_E, exit_gsd); 00417 } 00418 00419 if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) { 00420 goto exit_gsd; 00421 } 00422 mac->saltSz = size; 00423 mac->salt = (byte*)XMALLOC(mac->saltSz, pkcs12->heap, DYNAMIC_TYPE_SALT); 00424 if (mac->salt == NULL || mac->saltSz + curIdx > totalSz) { 00425 ERROR_OUT(MEMORY_E, exit_gsd); 00426 } 00427 XMEMCPY(mac->salt, mem + curIdx, mac->saltSz); 00428 00429 #ifdef WOLFSSL_DEBUG_PKCS12 00430 { 00431 byte* p; 00432 for (printf("\t\tSalt = "), p = (byte*)mem + curIdx; 00433 p < (byte*)mem + curIdx + mac->saltSz; 00434 printf("%02X", *p), p++); 00435 printf(" : size = %d\n", mac->saltSz); 00436 } 00437 #endif 00438 00439 curIdx += mac->saltSz; 00440 00441 /* check for MAC iterations, default to 1 */ 00442 mac->itt = WC_PKCS12_MAC_DEFAULT; 00443 if (curIdx < totalSz) { 00444 int number = 0; 00445 if ((ret = GetShortInt(mem, &curIdx, &number, totalSz)) >= 0) { 00446 /* found a iteration value */ 00447 mac->itt = number; 00448 } 00449 } 00450 00451 #ifdef WOLFSSL_DEBUG_PKCS12 00452 printf("\t\tITTERATIONS : %d\n", mac->itt); 00453 #endif 00454 00455 *idx = curIdx; 00456 pkcs12->signData = mac; 00457 ret = 0; /* success */ 00458 00459 exit_gsd: 00460 00461 /* failure cleanup */ 00462 if (ret != 0) { 00463 if (mac) { 00464 if (mac->digest) 00465 XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_DIGEST); 00466 XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00467 } 00468 } 00469 00470 return ret; 00471 } 00472 00473 00474 /* expects PKCS12 signData to be set up with OID 00475 * 00476 * returns the size of mac created on success. A negative value will be returned 00477 * in the case that an error happened. 00478 */ 00479 static int wc_PKCS12_create_mac(WC_PKCS12* pkcs12, byte* data, word32 dataSz, 00480 const byte* psw, word32 pswSz, byte* out, word32 outSz) 00481 { 00482 Hmac hmac; 00483 MacData* mac; 00484 int ret, kLen; 00485 enum wc_HashType hashT; 00486 int idx = 0; 00487 int id = 3; /* value from RFC 7292 indicating key is used for MAC */ 00488 word32 i; 00489 byte unicodePasswd[MAX_UNICODE_SZ]; 00490 byte key[MAX_KEY_SIZE]; 00491 00492 if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL || 00493 out == NULL) { 00494 return BAD_FUNC_ARG; 00495 } 00496 00497 mac = pkcs12->signData; 00498 00499 /* unicode set up from asn.c */ 00500 if ((pswSz * 2 + 2) > (int)sizeof(unicodePasswd)) { 00501 WOLFSSL_MSG("PKCS12 max unicode size too small"); 00502 return UNICODE_SIZE_E; 00503 } 00504 00505 for (i = 0; i < pswSz; i++) { 00506 unicodePasswd[idx++] = 0x00; 00507 unicodePasswd[idx++] = (byte)psw[i]; 00508 } 00509 /* add trailing NULL */ 00510 unicodePasswd[idx++] = 0x00; 00511 unicodePasswd[idx++] = 0x00; 00512 00513 /* get hash type used and resulting size of HMAC key */ 00514 hashT = wc_OidGetHash(mac->oid); 00515 if (hashT == WC_HASH_TYPE_NONE) { 00516 WOLFSSL_MSG("Unsupported hash used"); 00517 return BAD_FUNC_ARG; 00518 } 00519 kLen = wc_HashGetDigestSize(hashT); 00520 00521 /* check out buffer is large enough */ 00522 if (kLen < 0 || outSz < (word32)kLen) { 00523 return BAD_FUNC_ARG; 00524 } 00525 00526 /* idx contains size of unicodePasswd */ 00527 if ((ret = wc_PKCS12_PBKDF_ex(key, unicodePasswd, idx, mac->salt, 00528 mac->saltSz, mac->itt, kLen, (int)hashT, id, pkcs12->heap)) < 0) { 00529 return ret; 00530 } 00531 00532 /* now that key has been created use it to get HMAC hash on data */ 00533 if ((ret = wc_HmacInit(&hmac, pkcs12->heap, INVALID_DEVID)) != 0) { 00534 return ret; 00535 } 00536 ret = wc_HmacSetKey(&hmac, (int)hashT, key, kLen); 00537 if (ret == 0) 00538 ret = wc_HmacUpdate(&hmac, data, dataSz); 00539 if (ret == 0) 00540 ret = wc_HmacFinal(&hmac, out); 00541 wc_HmacFree(&hmac); 00542 00543 if (ret != 0) 00544 return ret; 00545 00546 return kLen; /* same as digest size */ 00547 } 00548 00549 00550 /* check mac on pkcs12, pkcs12->mac has been sanity checked before entering * 00551 * returns the result of comparison, success is 0 */ 00552 static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz, 00553 const byte* psw, word32 pswSz) 00554 { 00555 MacData* mac; 00556 int ret; 00557 byte digest[WC_MAX_DIGEST_SIZE]; 00558 00559 if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL) { 00560 return BAD_FUNC_ARG; 00561 } 00562 00563 mac = pkcs12->signData; 00564 00565 #ifdef WOLFSSL_DEBUG_PKCS12 00566 printf("Verifying MAC with OID = %d\n", mac->oid); 00567 #endif 00568 00569 /* check if this builds digest size is too small */ 00570 if (mac->digestSz > WC_MAX_DIGEST_SIZE) { 00571 WOLFSSL_MSG("PKCS12 max digest size too small"); 00572 return BAD_FUNC_ARG; 00573 } 00574 00575 if ((ret = wc_PKCS12_create_mac(pkcs12, data, dataSz, psw, pswSz, 00576 digest, WC_MAX_DIGEST_SIZE)) < 0) { 00577 return ret; 00578 } 00579 00580 #ifdef WOLFSSL_DEBUG_PKCS12 00581 { 00582 byte* p; 00583 for (printf("\t\tHash = "), p = (byte*)digest; 00584 p < (byte*)digest + mac->digestSz; 00585 printf("%02X", *p), p++); 00586 printf(" : size = %d\n", mac->digestSz); 00587 } 00588 #endif 00589 00590 return XMEMCMP(digest, mac->digest, mac->digestSz); 00591 } 00592 00593 00594 /* Convert DER format stored in der buffer to WC_PKCS12 struct 00595 * Puts the raw contents of Content Info into structure without completly 00596 * parsing or decoding. 00597 * der : pointer to der buffer holding PKCS12 00598 * derSz : size of der buffer 00599 * pkcs12 : non-null pkcs12 pointer 00600 * return 0 on success and negative on failure. 00601 */ 00602 int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12) 00603 { 00604 word32 idx = 0; 00605 word32 totalSz = 0; 00606 int ret; 00607 int size = 0; 00608 int version = 0; 00609 00610 WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio"); 00611 00612 if (der == NULL || pkcs12 == NULL) { 00613 return BAD_FUNC_ARG; 00614 } 00615 00616 totalSz = derSz; 00617 if ((ret = GetSequence(der, &idx, &size, totalSz)) <= 0) { 00618 WOLFSSL_MSG("Failed to get PKCS12 sequence"); 00619 return ret; 00620 } 00621 00622 /* get version */ 00623 if ((ret = GetMyVersion(der, &idx, &version, totalSz)) < 0) { 00624 return ret; 00625 } 00626 00627 #ifdef WOLFSSL_DEBUG_PKCS12 00628 printf("\nBEGIN: PKCS12 size = %d\n", totalSz); 00629 printf("version = %d\n", version); 00630 #endif 00631 00632 if (version != 3) { 00633 WOLFSSL_MSG("PKCS12 unsupported version!"); 00634 return ASN_VERSION_E; 00635 } 00636 00637 if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) { 00638 return ret; 00639 } 00640 00641 #ifdef WOLFSSL_DEBUG_PKCS12 00642 printf("\tSEQUENCE: AuthenticatedSafe size = %d\n", size); 00643 #endif 00644 00645 if ((ret = GetSafeContent(pkcs12, der, &idx, size + idx)) < 0) { 00646 WOLFSSL_MSG("GetSafeContent error"); 00647 return ret; 00648 } 00649 00650 /* if more buffer left check for MAC data */ 00651 if (idx < totalSz) { 00652 if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) { 00653 WOLFSSL_MSG("Ignoring unknown data at end of PKCS12 DER buffer"); 00654 } 00655 else { 00656 #ifdef WOLFSSL_DEBUG_PKCS12 00657 printf("\tSEQUENCE: Signature size = %d\n", size); 00658 #endif 00659 00660 if ((ret = GetSignData(pkcs12, der, &idx, totalSz)) < 0) { 00661 return ASN_PARSE_E; 00662 } 00663 } 00664 } 00665 00666 #ifdef WOLFSSL_DEBUG_PKCS12 00667 printf("END: PKCS12\n"); 00668 #endif 00669 00670 return ret; 00671 } 00672 00673 00674 /* helper function to free WC_DerCertList */ 00675 void wc_FreeCertList(WC_DerCertList* list, void* heap) 00676 { 00677 WC_DerCertList* current = list; 00678 WC_DerCertList* next; 00679 00680 if (list == NULL) { 00681 return; 00682 } 00683 00684 while (current != NULL) { 00685 next = current->next; 00686 if (current->buffer != NULL) { 00687 XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); 00688 } 00689 XFREE(current, heap, DYNAMIC_TYPE_PKCS); 00690 current = next; 00691 } 00692 00693 (void)heap; 00694 } 00695 00696 static void freeDecCertList(WC_DerCertList** list, byte** pkey, word32* pkeySz, 00697 byte** cert, word32* certSz, void* heap) 00698 { 00699 WC_DerCertList* current = *list; 00700 WC_DerCertList* previous = NULL; 00701 DecodedCert DeCert; 00702 00703 while (current != NULL) { 00704 00705 InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap); 00706 if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) { 00707 if (wc_CheckPrivateKey(*pkey, *pkeySz, &DeCert) == 1) { 00708 WOLFSSL_MSG("Key Pair found"); 00709 *cert = current->buffer; 00710 *certSz = current->bufferSz; 00711 00712 if (previous == NULL) { 00713 *list = current->next; 00714 } 00715 else { 00716 previous->next = current->next; 00717 } 00718 FreeDecodedCert(&DeCert); 00719 XFREE(current, heap, DYNAMIC_TYPE_PKCS); 00720 break; 00721 } 00722 } 00723 FreeDecodedCert(&DeCert); 00724 00725 previous = current; 00726 current = current->next; 00727 } 00728 } 00729 00730 00731 /* return 0 on success and negative on failure. 00732 * By side effect returns private key, cert, and optionally ca. 00733 * Parses and decodes the parts of PKCS12 00734 * 00735 * NOTE: can parse with USER RSA enabled but may return cert that is not the 00736 * pair for the key when using RSA key pairs. 00737 * 00738 * pkcs12 : non-null WC_PKCS12 struct 00739 * psw : password to use for PKCS12 decode 00740 * pkey : Private key returned 00741 * cert : x509 cert returned 00742 * ca : optional ca returned 00743 */ 00744 int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, 00745 byte** pkey, word32* pkeySz, byte** cert, word32* certSz, 00746 WC_DerCertList** ca) 00747 { 00748 ContentInfo* ci = NULL; 00749 WC_DerCertList* certList = NULL; 00750 WC_DerCertList* tailList = NULL; 00751 byte* buf = NULL; 00752 word32 i, oid; 00753 int ret, pswSz; 00754 00755 WOLFSSL_ENTER("wc_PKCS12_parse"); 00756 00757 if (pkcs12 == NULL || psw == NULL || cert == NULL || certSz == NULL || 00758 pkey == NULL || pkeySz == NULL) { 00759 return BAD_FUNC_ARG; 00760 } 00761 00762 pswSz = (int)XSTRLEN(psw); 00763 *cert = NULL; 00764 *pkey = NULL; 00765 if (ca != NULL) 00766 *ca = NULL; 00767 00768 /* if there is sign data then verify the MAC */ 00769 if (pkcs12->signData != NULL ) { 00770 if ((ret = wc_PKCS12_verify(pkcs12, pkcs12->safe->data, 00771 pkcs12->safe->dataSz, (byte*)psw, pswSz)) != 0) { 00772 WOLFSSL_MSG("PKCS12 Bad MAC on verify"); 00773 WOLFSSL_LEAVE("wc_PKCS12_parse verify ", ret); 00774 return MAC_CMP_FAILED_E; 00775 } 00776 } 00777 00778 if (pkcs12->safe == NULL) { 00779 WOLFSSL_MSG("No PKCS12 safes to parse"); 00780 return BAD_FUNC_ARG; 00781 } 00782 00783 /* Decode content infos */ 00784 ci = pkcs12->safe->CI; 00785 for (i = 0; i < pkcs12->safe->numCI; i++) { 00786 byte* data; 00787 word32 idx = 0; 00788 int size, totalSz; 00789 00790 if (ci->type == WC_PKCS12_ENCRYPTED_DATA) { 00791 int number; 00792 00793 WOLFSSL_MSG("Decrypting PKCS12 Content Info Container"); 00794 data = ci->data; 00795 if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00796 ERROR_OUT(ASN_PARSE_E, exit_pk12par); 00797 } 00798 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { 00799 goto exit_pk12par; 00800 } 00801 00802 if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) { 00803 goto exit_pk12par; 00804 } 00805 00806 if ((ret = GetShortInt(data, &idx, &number, ci->dataSz)) < 0) { 00807 goto exit_pk12par; 00808 } 00809 00810 if (number != 0) { 00811 WOLFSSL_MSG("Expecting 0 for Integer with Encrypted PKCS12"); 00812 } 00813 00814 if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) { 00815 goto exit_pk12par; 00816 } 00817 00818 ret = GetObjectId(data, &idx, &oid, oidIgnoreType, ci->dataSz); 00819 if (ret < 0 || oid != WC_PKCS12_DATA) { 00820 WOLFSSL_MSG("Not PKCS12 DATA object or get object parse error"); 00821 ERROR_OUT(ASN_PARSE_E, exit_pk12par); 00822 } 00823 00824 /* decrypted content overwrites input buffer */ 00825 size = ci->dataSz - idx; 00826 buf = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS); 00827 if (buf == NULL) { 00828 ERROR_OUT(MEMORY_E, exit_pk12par); 00829 } 00830 XMEMCPY(buf, data + idx, size); 00831 00832 if ((ret = DecryptContent(buf, size, psw, pswSz)) < 0) { 00833 WOLFSSL_MSG("Decryption failed, algorithm not compiled in?"); 00834 goto exit_pk12par; 00835 } 00836 00837 data = buf; 00838 idx = 0; 00839 00840 #ifdef WOLFSSL_DEBUG_PKCS12 00841 { 00842 byte* p; 00843 for (printf("\tData = "), p = (byte*)buf; 00844 p < (byte*)buf + size; 00845 printf("%02X", *p), p++); 00846 printf("\n"); 00847 } 00848 #endif 00849 } 00850 else { /* type DATA */ 00851 WOLFSSL_MSG("Parsing PKCS12 DATA Content Info Container"); 00852 data = ci->data; 00853 if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00854 ERROR_OUT(ASN_PARSE_E, exit_pk12par); 00855 } 00856 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { 00857 goto exit_pk12par; 00858 } 00859 if (data[idx++] != ASN_OCTET_STRING) { 00860 ERROR_OUT(ASN_PARSE_E, exit_pk12par); 00861 } 00862 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { 00863 goto exit_pk12par; 00864 } 00865 00866 } 00867 00868 /* parse through bags in ContentInfo */ 00869 if ((ret = GetSequence(data, &idx, &totalSz, ci->dataSz)) < 0) { 00870 goto exit_pk12par; 00871 } 00872 totalSz += idx; 00873 00874 while ((int)idx < totalSz) { 00875 int bagSz; 00876 if ((ret = GetSequence(data, &idx, &bagSz, ci->dataSz)) < 0) { 00877 goto exit_pk12par; 00878 } 00879 bagSz += idx; 00880 00881 if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType, 00882 ci->dataSz)) < 0) { 00883 goto exit_pk12par; 00884 } 00885 00886 switch (oid) { 00887 case WC_PKCS12_KeyBag: /* 667 */ 00888 WOLFSSL_MSG("PKCS12 Key Bag found"); 00889 if (data[idx++] != 00890 (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00891 ERROR_OUT(ASN_PARSE_E, exit_pk12par); 00892 } 00893 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { 00894 goto exit_pk12par; 00895 } 00896 if (*pkey == NULL) { 00897 *pkey = (byte*)XMALLOC(size, pkcs12->heap, 00898 DYNAMIC_TYPE_PUBLIC_KEY); 00899 if (*pkey == NULL) { 00900 ERROR_OUT(MEMORY_E, exit_pk12par); 00901 } 00902 XMEMCPY(*pkey, data + idx, size); 00903 *pkeySz = ToTraditional(*pkey, size); 00904 } 00905 00906 #ifdef WOLFSSL_DEBUG_PKCS12 00907 { 00908 byte* p; 00909 for (printf("\tKey = "), p = (byte*)*pkey; 00910 p < (byte*)*pkey + size; 00911 printf("%02X", *p), p++); 00912 printf("\n"); 00913 } 00914 #endif 00915 idx += size; 00916 break; 00917 00918 case WC_PKCS12_ShroudedKeyBag: /* 668 */ 00919 { 00920 byte* k; 00921 00922 WOLFSSL_MSG("PKCS12 Shrouded Key Bag found"); 00923 if (data[idx++] != 00924 (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00925 ERROR_OUT(ASN_PARSE_E, exit_pk12par); 00926 } 00927 if ((ret = GetLength(data, &idx, &size, 00928 ci->dataSz)) < 0) { 00929 goto exit_pk12par; 00930 } 00931 00932 k = (byte*)XMALLOC(size, pkcs12->heap, 00933 DYNAMIC_TYPE_PUBLIC_KEY); 00934 if (k == NULL) { 00935 ERROR_OUT(MEMORY_E, exit_pk12par); 00936 } 00937 XMEMCPY(k, data + idx, size); 00938 00939 /* overwrites input, be warned */ 00940 if ((ret = ToTraditionalEnc(k, size, psw, pswSz)) < 0) { 00941 XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); 00942 goto exit_pk12par; 00943 } 00944 00945 if (ret < size) { 00946 /* shrink key buffer */ 00947 byte* tmp = (byte*)XMALLOC(ret, pkcs12->heap, 00948 DYNAMIC_TYPE_PUBLIC_KEY); 00949 if (tmp == NULL) { 00950 XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); 00951 ERROR_OUT(MEMORY_E, exit_pk12par); 00952 } 00953 XMEMCPY(tmp, k, ret); 00954 XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); 00955 k = tmp; 00956 } 00957 size = ret; 00958 00959 if (*pkey == NULL) { 00960 *pkey = k; 00961 *pkeySz = size; 00962 } 00963 else { /* only expecting one key */ 00964 XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); 00965 } 00966 idx += size; 00967 00968 #ifdef WOLFSSL_DEBUG_PKCS12 00969 { 00970 byte* p; 00971 for (printf("\tKey = "), p = (byte*)k; 00972 p < (byte*)k + ret; 00973 printf("%02X", *p), p++); 00974 printf("\n"); 00975 } 00976 #endif 00977 } 00978 break; 00979 00980 case WC_PKCS12_CertBag: /* 669 */ 00981 { 00982 WC_DerCertList* node; 00983 WOLFSSL_MSG("PKCS12 Cert Bag found"); 00984 if (data[idx++] != 00985 (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 00986 ERROR_OUT(ASN_PARSE_E, exit_pk12par); 00987 } 00988 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { 00989 goto exit_pk12par; 00990 } 00991 00992 /* get cert bag type */ 00993 if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) <0) { 00994 goto exit_pk12par; 00995 } 00996 00997 if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType, 00998 ci->dataSz)) < 0) { 00999 goto exit_pk12par; 01000 } 01001 01002 switch (oid) { 01003 case WC_PKCS12_CertBag_Type1: /* 675 */ 01004 /* type 1 */ 01005 WOLFSSL_MSG("PKCS12 cert bag type 1"); 01006 if (data[idx++] != 01007 (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { 01008 ERROR_OUT(ASN_PARSE_E, exit_pk12par); 01009 } 01010 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) 01011 <= 0) { 01012 goto exit_pk12par; 01013 } 01014 if (data[idx++] != ASN_OCTET_STRING) { 01015 ERROR_OUT(ASN_PARSE_E, exit_pk12par); 01016 01017 } 01018 if ((ret = GetLength(data, &idx, &size, ci->dataSz)) 01019 < 0) { 01020 goto exit_pk12par; 01021 } 01022 break; 01023 default: 01024 WOLFSSL_MSG("Unknown PKCS12 cert bag type"); 01025 } 01026 01027 if (size + idx > (word32)bagSz) { 01028 ERROR_OUT(ASN_PARSE_E, exit_pk12par); 01029 } 01030 01031 /* list to hold all certs found */ 01032 node = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), 01033 pkcs12->heap, DYNAMIC_TYPE_PKCS); 01034 if (node == NULL) { 01035 ERROR_OUT(MEMORY_E, exit_pk12par); 01036 } 01037 XMEMSET(node, 0, sizeof(WC_DerCertList)); 01038 01039 node->buffer = (byte*)XMALLOC(size, pkcs12->heap, 01040 DYNAMIC_TYPE_PKCS); 01041 if (node->buffer == NULL) { 01042 XFREE(node, pkcs12->heap, DYNAMIC_TYPE_PKCS); 01043 ERROR_OUT(MEMORY_E, exit_pk12par); 01044 } 01045 XMEMCPY(node->buffer, data + idx, size); 01046 node->bufferSz = size; 01047 01048 /* put the new node into the list */ 01049 if (certList != NULL) { 01050 WOLFSSL_MSG("Pushing new cert onto queue"); 01051 tailList->next = node; 01052 tailList = node; 01053 } 01054 else { 01055 certList = node; 01056 tailList = node; 01057 } 01058 01059 /* on to next */ 01060 idx += size; 01061 } 01062 break; 01063 01064 case WC_PKCS12_CrlBag: /* 670 */ 01065 WOLFSSL_MSG("PKCS12 CRL BAG not yet supported"); 01066 break; 01067 01068 case WC_PKCS12_SecretBag: /* 671 */ 01069 WOLFSSL_MSG("PKCS12 Secret BAG not yet supported"); 01070 break; 01071 01072 case WC_PKCS12_SafeContentsBag: /* 672 */ 01073 WOLFSSL_MSG("PKCS12 Safe Contents BAG not yet supported"); 01074 break; 01075 01076 default: 01077 WOLFSSL_MSG("Unknown PKCS12 BAG type found"); 01078 } 01079 01080 /* Attribute, unknown bag or unsupported */ 01081 if ((int)idx < bagSz) { 01082 idx = bagSz; /* skip for now */ 01083 } 01084 } 01085 01086 /* free temporary buffer */ 01087 if (buf != NULL) { 01088 XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS); 01089 buf = NULL; 01090 } 01091 01092 ci = ci->next; 01093 WOLFSSL_MSG("Done Parsing PKCS12 Content Info Container"); 01094 } 01095 01096 /* check if key pair, remove from list */ 01097 if (*pkey != NULL) { 01098 freeDecCertList(&certList, pkey, pkeySz, cert, certSz, pkcs12->heap); 01099 } 01100 01101 /* if ca arg provided return certList, otherwise free it */ 01102 if (ca != NULL) { 01103 *ca = certList; 01104 } 01105 else { 01106 /* free list, not wanted */ 01107 wc_FreeCertList(certList, pkcs12->heap); 01108 } 01109 01110 ret = 0; /* success */ 01111 01112 exit_pk12par: 01113 01114 if (ret != 0) { 01115 /* failure cleanup */ 01116 if (*pkey) { 01117 XFREE(*pkey, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); 01118 *pkey = NULL; 01119 } 01120 if (buf) { 01121 XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS); 01122 buf = NULL; 01123 } 01124 01125 wc_FreeCertList(certList, pkcs12->heap); 01126 } 01127 01128 return ret; 01129 } 01130 01131 01132 /* Helper function to shroud keys. 01133 * 01134 * pkcs12 structure to use with shrouding key 01135 * rng random number generator used 01136 * out buffer to hold results 01137 * outSz size of out buffer 01138 * key key that is going to be shrouded 01139 * keySz size of key buffer 01140 * vAlgo algorithm version 01141 * pass password to use 01142 * passSz size of pass buffer 01143 * itt number of iterations 01144 * 01145 * returns the size of the shrouded key on success 01146 */ 01147 static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng, 01148 byte* out, word32* outSz, byte* key, word32 keySz, int vAlgo, 01149 const char* pass, int passSz, int itt) 01150 { 01151 void* heap; 01152 word32 tmpIdx = 0; 01153 int vPKCS = 1; /* PKCS#12 default set to 1 */ 01154 word32 sz; 01155 word32 totalSz = 0; 01156 int ret; 01157 01158 01159 if (outSz == NULL || pkcs12 == NULL || rng == NULL || key == NULL || 01160 pass == NULL) { 01161 return BAD_FUNC_ARG; 01162 } 01163 01164 heap = wc_PKCS12_GetHeap(pkcs12); 01165 01166 /* check if trying to get size */ 01167 if (out != NULL) { 01168 tmpIdx += MAX_LENGTH_SZ + 1; /* save room for length and tag (+1) */ 01169 sz = *outSz - tmpIdx; 01170 } 01171 01172 /* case of no encryption */ 01173 if (vAlgo < 0) { 01174 const byte* curveOID = NULL; 01175 word32 oidSz = 0; 01176 int algoID; 01177 01178 WOLFSSL_MSG("creating PKCS12 Key Bag"); 01179 01180 /* check key type and get OID if ECC */ 01181 if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap)) 01182 < 0) { 01183 return ret; 01184 } 01185 01186 /* PKCS#8 wrapping around key */ 01187 ret = wc_CreatePKCS8Key(out + tmpIdx, &sz, key, keySz, algoID, 01188 curveOID, oidSz); 01189 } 01190 else { 01191 WOLFSSL_MSG("creating PKCS12 Shrouded Key Bag"); 01192 01193 if (vAlgo == PBE_SHA1_DES) { 01194 vPKCS = PKCS5; 01195 vAlgo = 10; 01196 } 01197 01198 ret = UnTraditionalEnc(key, keySz, out + tmpIdx, &sz, pass, passSz, 01199 vPKCS, vAlgo, NULL, 0, itt, rng, heap); 01200 } 01201 if (ret == LENGTH_ONLY_E) { 01202 *outSz = sz + MAX_LENGTH_SZ + 1; 01203 return LENGTH_ONLY_E; 01204 } 01205 if (ret < 0) { 01206 return ret; 01207 } 01208 01209 totalSz += ret; 01210 01211 /* out should not be null at this point but check before writing */ 01212 if (out == NULL) { 01213 return BAD_FUNC_ARG; 01214 } 01215 01216 /* rewind index and set tag and length */ 01217 tmpIdx -= MAX_LENGTH_SZ + 1; 01218 sz = SetExplicit(0, ret, out + tmpIdx); 01219 tmpIdx += sz; totalSz += sz; 01220 XMEMMOVE(out + tmpIdx, out + MAX_LENGTH_SZ + 1, ret); 01221 01222 return totalSz; 01223 } 01224 01225 01226 /* Helper function to create key bag. 01227 * 01228 * pkcs12 structure to use with key bag 01229 * rng random number generator used 01230 * out buffer to hold results 01231 * outSz size of out buffer 01232 * key key that is going into key bag 01233 * keySz size of key buffer 01234 * algo algorithm version 01235 * iter number of iterations 01236 * pass password to use 01237 * passSz size of pass buffer 01238 * 01239 * returns the size of the key bag on success 01240 */ 01241 static int wc_PKCS12_create_key_bag(WC_PKCS12* pkcs12, WC_RNG* rng, 01242 byte* out, word32* outSz, byte* key, word32 keySz, int algo, int iter, 01243 char* pass, int passSz) 01244 { 01245 void* heap; 01246 byte* tmp; 01247 word32 length = 0; 01248 word32 idx = 0; 01249 word32 totalSz = 0; 01250 word32 sz; 01251 word32 i; 01252 word32 tmpSz; 01253 int ret; 01254 01255 /* get max size for shrouded key */ 01256 ret = wc_PKCS12_shroud_key(pkcs12, rng, NULL, &length, key, keySz, 01257 algo, pass, passSz, iter); 01258 if (ret != LENGTH_ONLY_E && ret < 0) { 01259 return ret; 01260 } 01261 01262 if (out == NULL) { 01263 *outSz = MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ + 1 + MAX_LENGTH_SZ + 01264 length; 01265 return LENGTH_ONLY_E; 01266 } 01267 01268 heap = wc_PKCS12_GetHeap(pkcs12); 01269 01270 /* leave room for sequence */ 01271 idx += MAX_SEQ_SZ; 01272 01273 if (algo < 0) { /* not encrypted */ 01274 out[idx++] = ASN_OBJECT_ID; totalSz++; 01275 sz = SetLength(sizeof(WC_PKCS12_KeyBag_OID), out + idx); 01276 idx += sz; totalSz += sz; 01277 for (i = 0; i < sizeof(WC_PKCS12_KeyBag_OID); i++) { 01278 out[idx++] = WC_PKCS12_KeyBag_OID[i]; totalSz++; 01279 } 01280 } 01281 else { /* encrypted */ 01282 out[idx++] = ASN_OBJECT_ID; totalSz++; 01283 sz = SetLength(sizeof(WC_PKCS12_ShroudedKeyBag_OID), out + idx); 01284 idx += sz; totalSz += sz; 01285 for (i = 0; i < sizeof(WC_PKCS12_ShroudedKeyBag_OID); i++) { 01286 out[idx++] = WC_PKCS12_ShroudedKeyBag_OID[i]; totalSz++; 01287 } 01288 } 01289 01290 /* shroud key */ 01291 tmp = (byte*)XMALLOC(length, heap, DYNAMIC_TYPE_TMP_BUFFER); 01292 if (tmp == NULL) { 01293 return MEMORY_E; 01294 } 01295 01296 ret = wc_PKCS12_shroud_key(pkcs12, rng, tmp, &length, key, keySz, 01297 algo, pass, passSz, iter); 01298 if (ret < 0) { 01299 XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); 01300 return ret; 01301 } 01302 length = ret; 01303 XMEMCPY(out + idx, tmp, length); 01304 XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); 01305 totalSz += length; 01306 01307 /* set begining sequence */ 01308 tmpSz = SetSequence(totalSz, out); 01309 XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz); 01310 01311 (void)heap; 01312 return totalSz + tmpSz; 01313 } 01314 01315 01316 /* Helper function to create cert bag. 01317 * 01318 * pkcs12 structure to use with cert bag 01319 * out buffer to hold results 01320 * outSz size of out buffer 01321 * cert cert that is going into cert bag 01322 * certSz size of cert buffer 01323 * 01324 * returns the size of the cert bag on success 01325 */ 01326 static int wc_PKCS12_create_cert_bag(WC_PKCS12* pkcs12, 01327 byte* out, word32* outSz, byte* cert, word32 certSz) 01328 { 01329 word32 length = 0; 01330 word32 idx = 0; 01331 word32 totalSz = 0; 01332 word32 sz; 01333 int WC_CERTBAG_OBJECT_ID = 13; 01334 int WC_CERTBAG1_OBJECT_ID = 12; 01335 word32 i; 01336 word32 tmpSz; 01337 01338 if (out == NULL) { 01339 *outSz = MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ + 01340 MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 + 01341 MAX_LENGTH_SZ + certSz; 01342 return LENGTH_ONLY_E; 01343 } 01344 01345 /* check buffer size able to handle max size */ 01346 if (*outSz < (MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ + 01347 MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 + 01348 MAX_LENGTH_SZ + certSz)) { 01349 return BUFFER_E; 01350 } 01351 01352 /* save room for sequence */ 01353 idx += MAX_SEQ_SZ; 01354 01355 /* objectId WC_PKCS12_CertBag */ 01356 out[idx++] = ASN_OBJECT_ID; totalSz++; 01357 sz = SetLength(sizeof(WC_PKCS12_CertBag_OID), out + idx); 01358 idx += sz; totalSz += sz; 01359 for (i = 0; i < sizeof(WC_PKCS12_CertBag_OID); i++) { 01360 out[idx++] = WC_PKCS12_CertBag_OID[i]; totalSz++; 01361 } 01362 01363 /**** Cert Bag type 1 ****/ 01364 out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); totalSz++; 01365 01366 /* save room for length and sequence */ 01367 idx += MAX_LENGTH_SZ; 01368 idx += MAX_SEQ_SZ; 01369 01370 /* object id WC_PKCS12_CertBag_Type1 */ 01371 out[idx++] = ASN_OBJECT_ID; length++; 01372 sz = SetLength(sizeof(WC_PKCS12_CertBag_Type1_OID), out + idx); 01373 idx += sz; length += sz; 01374 for (i = 0; i < sizeof(WC_PKCS12_CertBag_Type1_OID); i++) { 01375 out[idx++] = WC_PKCS12_CertBag_Type1_OID[i]; length++; 01376 } 01377 01378 out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); length++; 01379 sz = 0; 01380 idx += MAX_LENGTH_SZ; /* save room for length */ 01381 01382 /* place the cert in the buffer */ 01383 out[idx++] = ASN_OCTET_STRING; sz++; 01384 tmpSz = SetLength(certSz, out + idx); 01385 idx += tmpSz; sz += tmpSz; 01386 XMEMCPY(out + idx, cert, certSz); 01387 idx += certSz; sz += certSz; 01388 01389 /* rewind idx and place length */ 01390 idx -= (sz + MAX_LENGTH_SZ); 01391 tmpSz = SetLength(sz, out + idx); 01392 XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, sz); 01393 idx += tmpSz + sz; length += tmpSz + sz; 01394 01395 /* rewind idx and set sequence */ 01396 idx -= (length + MAX_SEQ_SZ); 01397 tmpSz = SetSequence(length, out + idx); 01398 XMEMMOVE(out + idx + tmpSz, out + idx + MAX_SEQ_SZ, length); 01399 length += tmpSz; 01400 01401 /* place final length */ 01402 idx -= MAX_LENGTH_SZ; 01403 tmpSz = SetLength(length, out + idx); 01404 XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length); 01405 length += tmpSz; 01406 01407 /* place final sequence */ 01408 totalSz += length; 01409 tmpSz = SetSequence(totalSz, out); 01410 XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz); 01411 01412 (void)pkcs12; 01413 01414 return totalSz + tmpSz; 01415 } 01416 01417 01418 /* Helper function to encrypt content. 01419 * 01420 * pkcs12 structure to use with key bag 01421 * rng random number generator used 01422 * out buffer to hold results 01423 * outSz size of out buffer 01424 * content content to encrypt 01425 * contentSz size of content buffer 01426 * vAlgo algorithm version 01427 * pass password to use 01428 * passSz size of pass buffer 01429 * iter number of iterations 01430 * type content type i.e WC_PKCS12_ENCRYPTED_DATA or WC_PKCS12_DATA 01431 * 01432 * returns the size of result on success 01433 */ 01434 static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, 01435 byte* out, word32* outSz, byte* content, word32 contentSz, int vAlgo, 01436 const char* pass, int passSz, int iter, int type) 01437 { 01438 void* heap; 01439 int vPKCS = 1; /* PKCS#12 is always set to 1 */ 01440 int ret; 01441 byte* tmp; 01442 word32 idx = 0; 01443 word32 totalSz = 0; 01444 word32 length = 0; 01445 word32 tmpSz; 01446 word32 encSz; 01447 word32 i; 01448 01449 WOLFSSL_MSG("encrypting PKCS12 content"); 01450 01451 heap = wc_PKCS12_GetHeap(pkcs12); 01452 01453 /* ENCRYPTED DATA 01454 * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC 01455 * length 01456 * sequence 01457 * short int 01458 * sequence 01459 * get object id */ 01460 if (type == WC_PKCS12_ENCRYPTED_DATA) { 01461 if (out == NULL) { 01462 *outSz = 1 + MAX_LENGTH_SZ + MAX_SEQ_SZ + MAX_VERSION_SZ + 01463 MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ; 01464 ret = EncryptContent(NULL, contentSz + MAX_SEQ_SZ, NULL, &encSz, 01465 pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap); 01466 if (ret != LENGTH_ONLY_E) { 01467 return ret; 01468 } 01469 01470 *outSz += encSz; 01471 return LENGTH_ONLY_E; 01472 } 01473 01474 if (*outSz < (1 + MAX_LENGTH_SZ + MAX_SEQ_SZ + MAX_VERSION_SZ)) { 01475 return BUFFER_E; 01476 } 01477 out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); totalSz++; 01478 01479 /* save room for length and sequence */ 01480 idx += MAX_LENGTH_SZ; 01481 idx += MAX_SEQ_SZ; 01482 01483 tmpSz = SetMyVersion(0, out + idx, 0); 01484 idx += tmpSz; length += tmpSz; 01485 01486 encSz = contentSz; 01487 if ((ret = EncryptContent(NULL, contentSz, NULL, &encSz, 01488 pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) { 01489 if (ret != LENGTH_ONLY_E) { 01490 return ret; 01491 } 01492 } 01493 01494 if (*outSz < (idx + MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ + encSz)) { 01495 return BUFFER_E; 01496 } 01497 tmp = (byte*)XMALLOC(encSz, heap, DYNAMIC_TYPE_TMP_BUFFER); 01498 if (tmp == NULL) { 01499 return MEMORY_E; 01500 } 01501 01502 if ((ret = EncryptContent(content, contentSz, tmp, &encSz, 01503 pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) { 01504 XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); 01505 return ret; 01506 } 01507 encSz = ret; 01508 01509 #ifdef WOLFSSL_DEBUG_PKCS12 01510 { 01511 byte* p; 01512 for (printf("(size %u) Encrypted Content = ", encSz), 01513 p = (byte*)tmp; 01514 p < (byte*)tmp + encSz; 01515 printf("%02X", *p), p++); 01516 printf("\n"); 01517 } 01518 #endif 01519 01520 tmpSz = SetSequence(WC_PKCS12_DATA_OBJ_SZ + encSz, out + idx); 01521 idx += tmpSz; length += tmpSz; 01522 01523 out[idx++] = ASN_OBJECT_ID; length++; 01524 tmpSz = SetLength(sizeof(WC_PKCS12_DATA_OID), out + idx); 01525 idx += tmpSz; length += tmpSz; 01526 for (i = 0; i < sizeof(WC_PKCS12_DATA_OID); i++) { 01527 out[idx++] = WC_PKCS12_DATA_OID[i]; length++; 01528 } 01529 01530 /* copy over encrypted data */ 01531 XMEMCPY(out + idx, tmp, encSz); 01532 XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); 01533 idx += encSz; length += encSz; 01534 01535 /* rewind and place sequence */ 01536 idx -= (length + MAX_SEQ_SZ); 01537 tmpSz = SetSequence(length, out + idx); 01538 XMEMMOVE(out + idx + tmpSz, out + idx + MAX_SEQ_SZ, length); 01539 length += tmpSz; 01540 01541 /* now place length */ 01542 idx -= MAX_LENGTH_SZ; 01543 tmpSz = SetLength(length, out + idx); 01544 XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length); 01545 totalSz += length + tmpSz; 01546 01547 return totalSz; 01548 } 01549 01550 /* DATA 01551 * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC 01552 * length 01553 * ASN_OCTET_STRING 01554 * length 01555 * sequence containing all bags */ 01556 if (type == WC_PKCS12_DATA) { 01557 if (out == NULL) { 01558 *outSz = 1 + MAX_LENGTH_SZ + 1 + MAX_LENGTH_SZ + contentSz; 01559 return LENGTH_ONLY_E; 01560 } 01561 01562 if (*outSz < (1 + MAX_LENGTH_SZ + 1 + MAX_LENGTH_SZ + contentSz)) { 01563 return BUFFER_E; 01564 } 01565 01566 out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); 01567 totalSz++; 01568 01569 /* save room for length */ 01570 idx += MAX_LENGTH_SZ; 01571 01572 out[idx++] = ASN_OCTET_STRING; length++; 01573 tmpSz = SetLength(contentSz, out + idx); 01574 idx += tmpSz; length += tmpSz; 01575 01576 /* sequence containing all bags */ 01577 XMEMCPY(out + idx, content, contentSz); 01578 idx += contentSz; length += contentSz; 01579 01580 idx -= (MAX_LENGTH_SZ + length); 01581 tmpSz = SetLength(length, out + idx); 01582 XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length); 01583 totalSz += length + tmpSz; 01584 01585 return totalSz; 01586 } 01587 01588 WOLFSSL_MSG("Unknown/Unsupported content type"); 01589 return BAD_FUNC_ARG; 01590 } 01591 01592 01593 /* 01594 * pass : password to use with encryption 01595 * passSz : size of the password buffer 01596 * name : friendlyName to use 01597 * key : DER format of key 01598 * keySz : size of key buffer 01599 * cert : DER format of certificate 01600 * certSz : size of the certificate buffer 01601 * ca : a list of extra certificates 01602 * nidKey : type of encryption to use on the key (-1 means no encryption) 01603 * nidCert : type of encryption to use on the certificate 01604 * (-1 means no encryption) 01605 * iter : number of iterations with encryption 01606 * macIter : number of iterations when creating MAC 01607 * keyType : flag for signature and/or encryption key 01608 * heap : pointer to allocate from memory 01609 * 01610 * returns a pointer to a new WC_PKCS12 structure on success and NULL if failed 01611 */ 01612 WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name, 01613 byte* key, word32 keySz, byte* cert, word32 certSz, WC_DerCertList* ca, 01614 int nidKey, int nidCert, int iter, int macIter, int keyType, void* heap) 01615 { 01616 WC_PKCS12* pkcs12; 01617 AuthenticatedSafe* safe; 01618 ContentInfo* ci; 01619 WC_RNG rng; 01620 int algo; 01621 int ret; 01622 int type; 01623 word32 idx; 01624 word32 sz; 01625 word32 tmpSz; 01626 01627 byte* certCi = NULL; 01628 word32 certCiSz; 01629 byte* keyCi; 01630 word32 keyCiSz; 01631 01632 byte* certBuf = NULL; 01633 word32 certBufSz; 01634 byte* keyBuf; 01635 word32 keyBufSz = 0; 01636 01637 WOLFSSL_ENTER("wc_PKCS12_create()"); 01638 01639 if ((ret = wc_InitRng_ex(&rng, heap, INVALID_DEVID)) != 0) { 01640 return NULL; 01641 } 01642 01643 if ((pkcs12 = wc_PKCS12_new()) == NULL) { 01644 wc_FreeRng(&rng); 01645 WOLFSSL_LEAVE("wc_PKCS12_create", MEMORY_E); 01646 return NULL; 01647 } 01648 01649 if ((ret = wc_PKCS12_SetHeap(pkcs12, heap)) != 0) { 01650 wc_PKCS12_free(pkcs12); 01651 wc_FreeRng(&rng); 01652 WOLFSSL_LEAVE("wc_PKCS12_create", ret); 01653 return NULL; 01654 } 01655 01656 if (iter <= 0) { 01657 iter = WC_PKCS12_ITT_DEFAULT; 01658 } 01659 01660 /**** add private key bag ****/ 01661 switch (nidKey) { 01662 case PBE_SHA1_RC4_128: 01663 algo = 1; 01664 break; 01665 01666 case PBE_SHA1_DES: 01667 algo = 2; 01668 break; 01669 01670 case PBE_SHA1_DES3: 01671 algo = 3; 01672 break; 01673 01674 /* no encryption */ 01675 case -1: 01676 algo = -1; 01677 break; 01678 01679 default: 01680 WOLFSSL_MSG("Unknown/Unsupported key encryption"); 01681 wc_PKCS12_free(pkcs12); 01682 wc_FreeRng(&rng); 01683 return NULL; 01684 } 01685 01686 /* get max size for key bag */ 01687 ret = wc_PKCS12_create_key_bag(pkcs12, &rng, NULL, &keyBufSz, key, keySz, 01688 algo, iter, pass, passSz); 01689 if (ret != LENGTH_ONLY_E && ret < 0) { 01690 wc_PKCS12_free(pkcs12); 01691 wc_FreeRng(&rng); 01692 WOLFSSL_LEAVE("wc_PKCS12_create", ret); 01693 return NULL; 01694 } 01695 01696 /* account for sequence around bag */ 01697 keyBufSz += MAX_SEQ_SZ; 01698 01699 keyBuf = (byte*)XMALLOC(keyBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER); 01700 if (keyBuf == NULL) { 01701 wc_PKCS12_free(pkcs12); 01702 wc_FreeRng(&rng); 01703 WOLFSSL_LEAVE("wc_PKCS12_create", MEMORY_E); 01704 return NULL; 01705 } 01706 01707 ret = wc_PKCS12_create_key_bag(pkcs12, &rng, keyBuf + MAX_SEQ_SZ, &keyBufSz, 01708 key, keySz, algo, iter, pass, passSz); 01709 if (ret < 0) { 01710 wc_PKCS12_free(pkcs12); 01711 wc_FreeRng(&rng); 01712 XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); 01713 WOLFSSL_LEAVE("wc_PKCS12_create", ret); 01714 return NULL; 01715 } 01716 keyBufSz = ret; 01717 01718 tmpSz = SetSequence(keyBufSz, keyBuf); 01719 XMEMMOVE(keyBuf + tmpSz, keyBuf + MAX_SEQ_SZ, keyBufSz); 01720 keyBufSz += tmpSz; 01721 01722 ret = wc_PKCS12_encrypt_content(pkcs12, &rng, NULL, &keyCiSz, 01723 NULL, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA); 01724 if (ret != LENGTH_ONLY_E) { 01725 wc_PKCS12_free(pkcs12); 01726 wc_FreeRng(&rng); 01727 XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); 01728 WOLFSSL_LEAVE("wc_PKCS12_create", ret); 01729 return NULL; 01730 } 01731 keyCi = (byte*)XMALLOC(keyCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER); 01732 if (keyCi == NULL) { 01733 wc_PKCS12_free(pkcs12); 01734 wc_FreeRng(&rng); 01735 XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); 01736 return NULL; 01737 } 01738 01739 ret = wc_PKCS12_encrypt_content(pkcs12, &rng, keyCi, &keyCiSz, 01740 keyBuf, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA); 01741 if (ret < 0 ) { 01742 wc_PKCS12_free(pkcs12); 01743 wc_FreeRng(&rng); 01744 XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); 01745 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01746 WOLFSSL_LEAVE("wc_PKCS12_create", ret); 01747 return NULL; 01748 } 01749 keyCiSz = ret; 01750 XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); 01751 01752 #ifdef WOLFSSL_DEBUG_PKCS12 01753 { 01754 byte* p; 01755 for (printf("(size %u) Key Content Info = ", keyCiSz), p = (byte*)keyCi; 01756 p < (byte*)keyCi + keyCiSz; 01757 printf("%02X", *p), p++); 01758 printf("\n"); 01759 } 01760 #endif 01761 01762 01763 /**** add main certificate bag and extras ****/ 01764 switch (nidCert) { 01765 case PBE_SHA1_RC4_128: 01766 type = WC_PKCS12_ENCRYPTED_DATA; 01767 algo = 1; 01768 break; 01769 01770 case PBE_SHA1_DES: 01771 type = WC_PKCS12_ENCRYPTED_DATA; 01772 algo = 2; 01773 break; 01774 01775 case PBE_SHA1_DES3: 01776 type = WC_PKCS12_ENCRYPTED_DATA; 01777 algo = 3; 01778 break; 01779 01780 case -1: 01781 type = WC_PKCS12_DATA; 01782 algo = -1; 01783 break; 01784 01785 default: 01786 WOLFSSL_MSG("Unknown/Unsupported certificate encryption"); 01787 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01788 wc_PKCS12_free(pkcs12); 01789 wc_FreeRng(&rng); 01790 return NULL; 01791 } 01792 01793 /* get max size of buffer needed */ 01794 ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &certBufSz, cert, certSz); 01795 if (ret != LENGTH_ONLY_E) { 01796 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01797 wc_PKCS12_free(pkcs12); 01798 wc_FreeRng(&rng); 01799 return NULL; 01800 } 01801 01802 if (ca != NULL) { 01803 WC_DerCertList* current = ca; 01804 word32 curBufSz = 0; 01805 01806 /* get max buffer size */ 01807 while (current != NULL) { 01808 ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &curBufSz, 01809 current->buffer, current->bufferSz); 01810 if (ret != LENGTH_ONLY_E) { 01811 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01812 wc_PKCS12_free(pkcs12); 01813 wc_FreeRng(&rng); 01814 return NULL; 01815 } 01816 certBufSz += curBufSz; 01817 current = current->next; 01818 } 01819 } 01820 01821 /* account for Sequence that holds all certificate bags */ 01822 certBufSz += MAX_SEQ_SZ; 01823 01824 /* completed getting max size, now create buffer and start adding bags */ 01825 certBuf = (byte*)XMALLOC(certBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER); 01826 if (certBuf == NULL) { 01827 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01828 wc_PKCS12_free(pkcs12); 01829 wc_FreeRng(&rng); 01830 WOLFSSL_MSG("Memory error creating certificate bags"); 01831 return NULL; 01832 } 01833 01834 idx = 0; 01835 idx += MAX_SEQ_SZ; 01836 01837 sz = certBufSz - idx; 01838 if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz, 01839 cert, certSz)) < 0) { 01840 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01841 XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); 01842 wc_PKCS12_free(pkcs12); 01843 wc_FreeRng(&rng); 01844 return NULL; 01845 } 01846 idx += ret; 01847 01848 if (ca != NULL) { 01849 WC_DerCertList* current = ca; 01850 01851 while (current != NULL) { 01852 sz = certBufSz - idx; 01853 if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz, 01854 current->buffer, current->bufferSz)) < 0) { 01855 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01856 XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); 01857 wc_PKCS12_free(pkcs12); 01858 wc_FreeRng(&rng); 01859 return NULL; 01860 } 01861 idx += ret; 01862 current = current->next; 01863 } 01864 } 01865 01866 /* set sequence and create encrypted content with all certificate bags */ 01867 tmpSz = SetSequence(idx - MAX_SEQ_SZ, certBuf); 01868 XMEMMOVE(certBuf + tmpSz, certBuf + MAX_SEQ_SZ, idx - MAX_SEQ_SZ); 01869 certBufSz = tmpSz + (idx - MAX_SEQ_SZ); 01870 01871 /* get buffer size needed for content info */ 01872 ret = wc_PKCS12_encrypt_content(pkcs12, &rng, NULL, &certCiSz, 01873 NULL, certBufSz, algo, pass, passSz, iter, type); 01874 if (ret != LENGTH_ONLY_E) { 01875 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01876 XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); 01877 wc_PKCS12_free(pkcs12); 01878 wc_FreeRng(&rng); 01879 WOLFSSL_LEAVE("wc_PKCS12_create()", ret); 01880 return NULL; 01881 } 01882 certCi = (byte*)XMALLOC(certCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER); 01883 if (certCi == NULL) { 01884 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01885 XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); 01886 wc_PKCS12_free(pkcs12); 01887 wc_FreeRng(&rng); 01888 return NULL; 01889 } 01890 01891 ret = wc_PKCS12_encrypt_content(pkcs12, &rng, certCi, &certCiSz, 01892 certBuf, certBufSz, algo, pass, passSz, iter, type); 01893 if (ret < 0) { 01894 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01895 XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); 01896 XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01897 wc_PKCS12_free(pkcs12); 01898 wc_FreeRng(&rng); 01899 WOLFSSL_LEAVE("wc_PKCS12_create()", ret); 01900 return NULL; 01901 } 01902 certCiSz = ret; 01903 XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); 01904 01905 #ifdef WOLFSSL_DEBUG_PKCS12 01906 { 01907 byte* p; 01908 for (printf("(size %u) Encrypted Certificate Content Info = ",certCiSz), 01909 p = (byte*)certCi; 01910 p < (byte*)certCi + certCiSz; 01911 printf("%02X", *p), p++); 01912 printf("\n"); 01913 } 01914 #endif 01915 01916 /**** create safe and and Content Info ****/ 01917 safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), heap, 01918 DYNAMIC_TYPE_PKCS); 01919 if (safe == NULL) { 01920 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01921 XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01922 wc_PKCS12_free(pkcs12); 01923 wc_FreeRng(&rng); 01924 return NULL; 01925 } 01926 pkcs12->safe = safe; /* set so all of safe is free'd with wc_PKCS12_free */ 01927 XMEMSET(safe, 0, sizeof(AuthenticatedSafe)); 01928 01929 safe->dataSz = certCiSz + keyCiSz; 01930 safe->data = (byte*)XMALLOC(safe->dataSz, heap, DYNAMIC_TYPE_PKCS); 01931 if (safe->data == NULL) { 01932 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01933 XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01934 wc_PKCS12_free(pkcs12); 01935 wc_FreeRng(&rng); 01936 return NULL; 01937 } 01938 XMEMCPY(safe->data, certCi, certCiSz); 01939 XMEMCPY(safe->data + certCiSz, keyCi, keyCiSz); 01940 XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01941 XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); 01942 01943 safe->numCI = 2; 01944 01945 /* add Content Info structs to safe, key first then cert */ 01946 ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), heap, DYNAMIC_TYPE_PKCS); 01947 if (ci == NULL) { 01948 wc_PKCS12_free(pkcs12); 01949 wc_FreeRng(&rng); 01950 return NULL; 01951 } 01952 XMEMSET(ci, 0, sizeof(ContentInfo)); 01953 safe->CI = ci; 01954 ci->data = safe->data + certCiSz; 01955 ci->dataSz = keyCiSz; 01956 ci->type = WC_PKCS12_DATA; 01957 01958 ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), heap, DYNAMIC_TYPE_PKCS); 01959 if (ci == NULL) { 01960 wc_PKCS12_free(pkcs12); 01961 wc_FreeRng(&rng); 01962 return NULL; 01963 } 01964 XMEMSET(ci, 0, sizeof(ContentInfo)); 01965 ci->next = safe->CI; 01966 safe->CI = ci; 01967 ci->data = safe->data; 01968 ci->dataSz = certCiSz; 01969 if (nidCert < 0) { 01970 ci->type = WC_PKCS12_DATA; 01971 } 01972 else { 01973 ci->type = WC_PKCS12_ENCRYPTED_DATA; 01974 } 01975 01976 /* create MAC */ 01977 if (macIter > 0) { 01978 MacData* mac; 01979 byte digest[WC_MAX_DIGEST_SIZE]; /* for MAC */ 01980 01981 mac = (MacData*)XMALLOC(sizeof(MacData), heap, DYNAMIC_TYPE_PKCS); 01982 if (mac == NULL) { 01983 wc_PKCS12_free(pkcs12); 01984 wc_FreeRng(&rng); 01985 return NULL; 01986 } 01987 XMEMSET(mac, 0, sizeof(MacData)); 01988 pkcs12->signData = mac; /* now wc_PKCS12_free will free all mac too */ 01989 01990 #ifndef NO_SHA256 01991 mac->oid = SHA256h; 01992 #elif !defined(NO_SHA) 01993 mac->oid = SHA; 01994 #elif defined(WOLFSSL_SHA384) 01995 mac->oid = SHA384; 01996 #elif defined(WOLFSSL_SHA512) 01997 mac->oid = SHA512; 01998 #else 01999 WOLFSSL_MSG("No supported hash algorithm compiled in!"); 02000 wc_PKCS12_free(pkcs12); 02001 wc_FreeRng(&rng); 02002 return NULL; 02003 #endif 02004 02005 /* store number of iterations */ 02006 mac->itt = macIter; 02007 02008 /* set mac salt */ 02009 mac->saltSz = 8; 02010 mac->salt = (byte*)XMALLOC(mac->saltSz, heap, DYNAMIC_TYPE_PKCS); 02011 if (mac->salt == NULL) { 02012 wc_PKCS12_free(pkcs12); 02013 wc_FreeRng(&rng); 02014 return NULL; 02015 } 02016 02017 if ((ret = wc_RNG_GenerateBlock(&rng, mac->salt, mac->saltSz)) != 0) { 02018 WOLFSSL_MSG("Error generating random salt"); 02019 wc_PKCS12_free(pkcs12); 02020 wc_FreeRng(&rng); 02021 return NULL; 02022 } 02023 ret = wc_PKCS12_create_mac(pkcs12, safe->data, safe->dataSz, 02024 (const byte*)pass, passSz, digest, WC_MAX_DIGEST_SIZE); 02025 if (ret < 0) { 02026 wc_PKCS12_free(pkcs12); 02027 wc_FreeRng(&rng); 02028 return NULL; 02029 } 02030 02031 mac->digestSz = ret; 02032 mac->digest = (byte*)XMALLOC(ret, heap, DYNAMIC_TYPE_PKCS); 02033 if (mac->digest == NULL) { 02034 wc_PKCS12_free(pkcs12); 02035 wc_FreeRng(&rng); 02036 return NULL; 02037 } 02038 XMEMCPY(mac->digest, digest, mac->digestSz); 02039 } 02040 else { 02041 pkcs12->signData = NULL; 02042 } 02043 02044 wc_FreeRng(&rng); 02045 (void)name; 02046 (void)keyType; 02047 02048 return pkcs12; 02049 } 02050 02051 02052 /* if using a specific memory heap */ 02053 int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap) 02054 { 02055 if (pkcs12 == NULL) { 02056 return BAD_FUNC_ARG; 02057 } 02058 pkcs12->heap = heap; 02059 02060 return 0; 02061 } 02062 02063 02064 /* getter for heap */ 02065 void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12) 02066 { 02067 if (pkcs12 == NULL) { 02068 return NULL; 02069 } 02070 02071 return pkcs12->heap; 02072 } 02073 02074 #undef ERROR_OUT 02075 02076 #endif /* !NO_ASN && !NO_PWDBASED */ 02077
Generated on Tue Jul 12 2022 16:58:06 by
1.7.2