wolf SSL / wolfSSL-TLS13-Beta

Fork of wolfSSL by wolf SSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pkcs12.c Source File

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