wolfSSL SSL/TLS library, support up to TLS1.3
Dependents: CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more
wolfcrypt/src/pkcs12.c@17:a5f916481144, 2020-06-05 (annotated)
- Committer:
- wolfSSL
- Date:
- Fri Jun 05 00:11:07 2020 +0000
- Revision:
- 17:a5f916481144
- Parent:
- 16:8e0d178b1d1e
wolfSSL 4.4.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
wolfSSL | 15:117db924cf7c | 1 | /* pkcs12.c |
wolfSSL | 15:117db924cf7c | 2 | * |
wolfSSL | 16:8e0d178b1d1e | 3 | * Copyright (C) 2006-2020 wolfSSL Inc. |
wolfSSL | 15:117db924cf7c | 4 | * |
wolfSSL | 15:117db924cf7c | 5 | * This file is part of wolfSSL. |
wolfSSL | 15:117db924cf7c | 6 | * |
wolfSSL | 15:117db924cf7c | 7 | * wolfSSL is free software; you can redistribute it and/or modify |
wolfSSL | 15:117db924cf7c | 8 | * it under the terms of the GNU General Public License as published by |
wolfSSL | 15:117db924cf7c | 9 | * the Free Software Foundation; either version 2 of the License, or |
wolfSSL | 15:117db924cf7c | 10 | * (at your option) any later version. |
wolfSSL | 15:117db924cf7c | 11 | * |
wolfSSL | 15:117db924cf7c | 12 | * wolfSSL is distributed in the hope that it will be useful, |
wolfSSL | 15:117db924cf7c | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
wolfSSL | 15:117db924cf7c | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
wolfSSL | 15:117db924cf7c | 15 | * GNU General Public License for more details. |
wolfSSL | 15:117db924cf7c | 16 | * |
wolfSSL | 15:117db924cf7c | 17 | * You should have received a copy of the GNU General Public License |
wolfSSL | 15:117db924cf7c | 18 | * along with this program; if not, write to the Free Software |
wolfSSL | 15:117db924cf7c | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA |
wolfSSL | 15:117db924cf7c | 20 | */ |
wolfSSL | 15:117db924cf7c | 21 | |
wolfSSL | 15:117db924cf7c | 22 | |
wolfSSL | 15:117db924cf7c | 23 | #ifdef HAVE_CONFIG_H |
wolfSSL | 15:117db924cf7c | 24 | #include <config.h> |
wolfSSL | 15:117db924cf7c | 25 | #endif |
wolfSSL | 15:117db924cf7c | 26 | |
wolfSSL | 15:117db924cf7c | 27 | #include <wolfssl/wolfcrypt/settings.h> |
wolfSSL | 15:117db924cf7c | 28 | |
wolfSSL | 16:8e0d178b1d1e | 29 | #if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12) |
wolfSSL | 15:117db924cf7c | 30 | |
wolfSSL | 15:117db924cf7c | 31 | #include <wolfssl/wolfcrypt/asn.h> |
wolfSSL | 15:117db924cf7c | 32 | #include <wolfssl/wolfcrypt/asn_public.h> |
wolfSSL | 15:117db924cf7c | 33 | #include <wolfssl/wolfcrypt/error-crypt.h> |
wolfSSL | 15:117db924cf7c | 34 | #include <wolfssl/wolfcrypt/hmac.h> |
wolfSSL | 15:117db924cf7c | 35 | #include <wolfssl/wolfcrypt/logging.h> |
wolfSSL | 15:117db924cf7c | 36 | #ifdef NO_INLINE |
wolfSSL | 15:117db924cf7c | 37 | #include <wolfssl/wolfcrypt/misc.h> |
wolfSSL | 15:117db924cf7c | 38 | #else |
wolfSSL | 15:117db924cf7c | 39 | #define WOLFSSL_MISC_INCLUDED |
wolfSSL | 15:117db924cf7c | 40 | #include <wolfcrypt/src/misc.c> |
wolfSSL | 15:117db924cf7c | 41 | #endif |
wolfSSL | 15:117db924cf7c | 42 | #include <wolfssl/wolfcrypt/pkcs12.h> |
wolfSSL | 15:117db924cf7c | 43 | #include <wolfssl/wolfcrypt/pwdbased.h> |
wolfSSL | 15:117db924cf7c | 44 | #include <wolfssl/wolfcrypt/hash.h> |
wolfSSL | 15:117db924cf7c | 45 | |
wolfSSL | 15:117db924cf7c | 46 | |
wolfSSL | 15:117db924cf7c | 47 | #define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } |
wolfSSL | 15:117db924cf7c | 48 | |
wolfSSL | 15:117db924cf7c | 49 | enum { |
wolfSSL | 15:117db924cf7c | 50 | WC_PKCS12_KeyBag = 667, |
wolfSSL | 15:117db924cf7c | 51 | WC_PKCS12_ShroudedKeyBag = 668, |
wolfSSL | 15:117db924cf7c | 52 | WC_PKCS12_CertBag = 669, |
wolfSSL | 15:117db924cf7c | 53 | WC_PKCS12_CertBag_Type1 = 675, |
wolfSSL | 15:117db924cf7c | 54 | WC_PKCS12_CrlBag = 670, |
wolfSSL | 15:117db924cf7c | 55 | WC_PKCS12_SecretBag = 671, |
wolfSSL | 15:117db924cf7c | 56 | WC_PKCS12_SafeContentsBag = 672, |
wolfSSL | 15:117db924cf7c | 57 | WC_PKCS12_DATA = 651, |
wolfSSL | 15:117db924cf7c | 58 | WC_PKCS12_ENCRYPTED_DATA = 656, |
wolfSSL | 15:117db924cf7c | 59 | |
wolfSSL | 15:117db924cf7c | 60 | WC_PKCS12_DATA_OBJ_SZ = 11, |
wolfSSL | 15:117db924cf7c | 61 | }; |
wolfSSL | 15:117db924cf7c | 62 | |
wolfSSL | 16:8e0d178b1d1e | 63 | static const byte WC_PKCS12_ENCRYPTED_OID[] = |
wolfSSL | 16:8e0d178b1d1e | 64 | {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06}; |
wolfSSL | 15:117db924cf7c | 65 | static const byte WC_PKCS12_DATA_OID[] = |
wolfSSL | 15:117db924cf7c | 66 | {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01}; |
wolfSSL | 15:117db924cf7c | 67 | static const byte WC_PKCS12_CertBag_Type1_OID[] = |
wolfSSL | 15:117db924cf7c | 68 | {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x16, 0x01}; |
wolfSSL | 15:117db924cf7c | 69 | static const byte WC_PKCS12_CertBag_OID[] = |
wolfSSL | 15:117db924cf7c | 70 | {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x03}; |
wolfSSL | 15:117db924cf7c | 71 | static const byte WC_PKCS12_KeyBag_OID[] = |
wolfSSL | 15:117db924cf7c | 72 | {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x01}; |
wolfSSL | 15:117db924cf7c | 73 | static const byte WC_PKCS12_ShroudedKeyBag_OID[] = |
wolfSSL | 15:117db924cf7c | 74 | {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x02}; |
wolfSSL | 15:117db924cf7c | 75 | |
wolfSSL | 15:117db924cf7c | 76 | |
wolfSSL | 15:117db924cf7c | 77 | typedef struct ContentInfo { |
wolfSSL | 15:117db924cf7c | 78 | byte* data; |
wolfSSL | 15:117db924cf7c | 79 | struct ContentInfo* next; |
wolfSSL | 15:117db924cf7c | 80 | word32 encC; /* encryptedContent */ |
wolfSSL | 15:117db924cf7c | 81 | word32 dataSz; |
wolfSSL | 16:8e0d178b1d1e | 82 | int type; /* DATA / encrypted / enveloped */ |
wolfSSL | 15:117db924cf7c | 83 | } ContentInfo; |
wolfSSL | 15:117db924cf7c | 84 | |
wolfSSL | 15:117db924cf7c | 85 | |
wolfSSL | 15:117db924cf7c | 86 | typedef struct AuthenticatedSafe { |
wolfSSL | 15:117db924cf7c | 87 | ContentInfo* CI; |
wolfSSL | 15:117db924cf7c | 88 | byte* data; /* T contents.... */ |
wolfSSL | 15:117db924cf7c | 89 | word32 oid; /* encrypted or not */ |
wolfSSL | 15:117db924cf7c | 90 | word32 numCI; /* number of Content Info structs */ |
wolfSSL | 15:117db924cf7c | 91 | word32 dataSz; |
wolfSSL | 15:117db924cf7c | 92 | } AuthenticatedSafe; |
wolfSSL | 15:117db924cf7c | 93 | |
wolfSSL | 15:117db924cf7c | 94 | |
wolfSSL | 15:117db924cf7c | 95 | typedef struct MacData { |
wolfSSL | 15:117db924cf7c | 96 | byte* digest; |
wolfSSL | 15:117db924cf7c | 97 | byte* salt; |
wolfSSL | 15:117db924cf7c | 98 | word32 oid; |
wolfSSL | 15:117db924cf7c | 99 | word32 digestSz; |
wolfSSL | 15:117db924cf7c | 100 | word32 saltSz; |
wolfSSL | 16:8e0d178b1d1e | 101 | int itt; /* number of iterations when creating HMAC key */ |
wolfSSL | 15:117db924cf7c | 102 | } MacData; |
wolfSSL | 15:117db924cf7c | 103 | |
wolfSSL | 15:117db924cf7c | 104 | |
wolfSSL | 15:117db924cf7c | 105 | struct WC_PKCS12 { |
wolfSSL | 15:117db924cf7c | 106 | void* heap; |
wolfSSL | 15:117db924cf7c | 107 | AuthenticatedSafe* safe; |
wolfSSL | 15:117db924cf7c | 108 | MacData* signData; |
wolfSSL | 15:117db924cf7c | 109 | word32 oid; /* DATA / Enveloped DATA ... */ |
wolfSSL | 15:117db924cf7c | 110 | }; |
wolfSSL | 15:117db924cf7c | 111 | |
wolfSSL | 15:117db924cf7c | 112 | |
wolfSSL | 15:117db924cf7c | 113 | /* for friendlyName, localKeyId .... */ |
wolfSSL | 15:117db924cf7c | 114 | typedef struct WC_PKCS12_ATTRIBUTE { |
wolfSSL | 15:117db924cf7c | 115 | byte* data; |
wolfSSL | 15:117db924cf7c | 116 | word32 oid; |
wolfSSL | 15:117db924cf7c | 117 | word32 dataSz; |
wolfSSL | 15:117db924cf7c | 118 | } WC_PKCS12_ATTRIBUTE; |
wolfSSL | 15:117db924cf7c | 119 | |
wolfSSL | 15:117db924cf7c | 120 | |
wolfSSL | 15:117db924cf7c | 121 | WC_PKCS12* wc_PKCS12_new(void) |
wolfSSL | 15:117db924cf7c | 122 | { |
wolfSSL | 15:117db924cf7c | 123 | WC_PKCS12* pkcs12 = (WC_PKCS12*)XMALLOC(sizeof(WC_PKCS12), |
wolfSSL | 15:117db924cf7c | 124 | NULL, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 125 | if (pkcs12 == NULL) { |
wolfSSL | 15:117db924cf7c | 126 | WOLFSSL_MSG("Memory issue when creating WC_PKCS12 struct"); |
wolfSSL | 15:117db924cf7c | 127 | return NULL; |
wolfSSL | 15:117db924cf7c | 128 | } |
wolfSSL | 15:117db924cf7c | 129 | |
wolfSSL | 15:117db924cf7c | 130 | XMEMSET(pkcs12, 0, sizeof(WC_PKCS12)); |
wolfSSL | 15:117db924cf7c | 131 | |
wolfSSL | 15:117db924cf7c | 132 | return pkcs12; |
wolfSSL | 15:117db924cf7c | 133 | } |
wolfSSL | 15:117db924cf7c | 134 | |
wolfSSL | 15:117db924cf7c | 135 | |
wolfSSL | 15:117db924cf7c | 136 | static void freeSafe(AuthenticatedSafe* safe, void* heap) |
wolfSSL | 15:117db924cf7c | 137 | { |
wolfSSL | 15:117db924cf7c | 138 | int i; |
wolfSSL | 15:117db924cf7c | 139 | |
wolfSSL | 15:117db924cf7c | 140 | if (safe == NULL) { |
wolfSSL | 15:117db924cf7c | 141 | return; |
wolfSSL | 15:117db924cf7c | 142 | } |
wolfSSL | 15:117db924cf7c | 143 | |
wolfSSL | 15:117db924cf7c | 144 | /* free content info structs */ |
wolfSSL | 15:117db924cf7c | 145 | for (i = safe->numCI; i > 0; i--) { |
wolfSSL | 15:117db924cf7c | 146 | ContentInfo* ci = safe->CI; |
wolfSSL | 15:117db924cf7c | 147 | safe->CI = ci->next; |
wolfSSL | 15:117db924cf7c | 148 | XFREE(ci, heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 149 | } |
wolfSSL | 15:117db924cf7c | 150 | if (safe->data != NULL) { |
wolfSSL | 15:117db924cf7c | 151 | XFREE(safe->data, heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 152 | } |
wolfSSL | 15:117db924cf7c | 153 | XFREE(safe, heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 154 | |
wolfSSL | 15:117db924cf7c | 155 | (void)heap; |
wolfSSL | 15:117db924cf7c | 156 | } |
wolfSSL | 15:117db924cf7c | 157 | |
wolfSSL | 15:117db924cf7c | 158 | |
wolfSSL | 15:117db924cf7c | 159 | void wc_PKCS12_free(WC_PKCS12* pkcs12) |
wolfSSL | 15:117db924cf7c | 160 | { |
wolfSSL | 15:117db924cf7c | 161 | void* heap; |
wolfSSL | 15:117db924cf7c | 162 | |
wolfSSL | 15:117db924cf7c | 163 | /* if null pointer is passed in do nothing */ |
wolfSSL | 15:117db924cf7c | 164 | if (pkcs12 == NULL) { |
wolfSSL | 15:117db924cf7c | 165 | WOLFSSL_MSG("Trying to free null WC_PKCS12 object"); |
wolfSSL | 15:117db924cf7c | 166 | return; |
wolfSSL | 15:117db924cf7c | 167 | } |
wolfSSL | 15:117db924cf7c | 168 | |
wolfSSL | 15:117db924cf7c | 169 | heap = pkcs12->heap; |
wolfSSL | 15:117db924cf7c | 170 | if (pkcs12->safe != NULL) { |
wolfSSL | 15:117db924cf7c | 171 | freeSafe(pkcs12->safe, heap); |
wolfSSL | 15:117db924cf7c | 172 | } |
wolfSSL | 15:117db924cf7c | 173 | |
wolfSSL | 15:117db924cf7c | 174 | /* free mac data */ |
wolfSSL | 15:117db924cf7c | 175 | if (pkcs12->signData != NULL) { |
wolfSSL | 15:117db924cf7c | 176 | if (pkcs12->signData->digest != NULL) { |
wolfSSL | 15:117db924cf7c | 177 | XFREE(pkcs12->signData->digest, heap, DYNAMIC_TYPE_DIGEST); |
wolfSSL | 15:117db924cf7c | 178 | pkcs12->signData->digest = NULL; |
wolfSSL | 15:117db924cf7c | 179 | } |
wolfSSL | 15:117db924cf7c | 180 | if (pkcs12->signData->salt != NULL) { |
wolfSSL | 15:117db924cf7c | 181 | XFREE(pkcs12->signData->salt, heap, DYNAMIC_TYPE_SALT); |
wolfSSL | 15:117db924cf7c | 182 | pkcs12->signData->salt = NULL; |
wolfSSL | 15:117db924cf7c | 183 | } |
wolfSSL | 15:117db924cf7c | 184 | XFREE(pkcs12->signData, heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 185 | pkcs12->signData = NULL; |
wolfSSL | 15:117db924cf7c | 186 | } |
wolfSSL | 15:117db924cf7c | 187 | |
wolfSSL | 15:117db924cf7c | 188 | XFREE(pkcs12, NULL, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 189 | pkcs12 = NULL; |
wolfSSL | 15:117db924cf7c | 190 | } |
wolfSSL | 15:117db924cf7c | 191 | |
wolfSSL | 15:117db924cf7c | 192 | |
wolfSSL | 15:117db924cf7c | 193 | static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, |
wolfSSL | 15:117db924cf7c | 194 | word32* idx, int maxIdx) |
wolfSSL | 15:117db924cf7c | 195 | { |
wolfSSL | 15:117db924cf7c | 196 | AuthenticatedSafe* safe; |
wolfSSL | 15:117db924cf7c | 197 | word32 oid; |
wolfSSL | 15:117db924cf7c | 198 | word32 localIdx = *idx; |
wolfSSL | 15:117db924cf7c | 199 | int ret; |
wolfSSL | 15:117db924cf7c | 200 | int size = 0; |
wolfSSL | 16:8e0d178b1d1e | 201 | byte tag; |
wolfSSL | 15:117db924cf7c | 202 | |
wolfSSL | 15:117db924cf7c | 203 | safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), pkcs12->heap, |
wolfSSL | 15:117db924cf7c | 204 | DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 205 | if (safe == NULL) { |
wolfSSL | 15:117db924cf7c | 206 | return MEMORY_E; |
wolfSSL | 15:117db924cf7c | 207 | } |
wolfSSL | 15:117db924cf7c | 208 | XMEMSET(safe, 0, sizeof(AuthenticatedSafe)); |
wolfSSL | 15:117db924cf7c | 209 | |
wolfSSL | 15:117db924cf7c | 210 | ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, maxIdx); |
wolfSSL | 15:117db924cf7c | 211 | if (ret < 0) { |
wolfSSL | 15:117db924cf7c | 212 | WOLFSSL_LEAVE("Get object id failed", ret); |
wolfSSL | 15:117db924cf7c | 213 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 214 | return ASN_PARSE_E; |
wolfSSL | 15:117db924cf7c | 215 | } |
wolfSSL | 15:117db924cf7c | 216 | |
wolfSSL | 15:117db924cf7c | 217 | safe->oid = oid; |
wolfSSL | 15:117db924cf7c | 218 | /* check tag, length */ |
wolfSSL | 16:8e0d178b1d1e | 219 | if (GetASNTag(input, &localIdx, &tag, maxIdx) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 220 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 16:8e0d178b1d1e | 221 | return ASN_PARSE_E; |
wolfSSL | 16:8e0d178b1d1e | 222 | } |
wolfSSL | 16:8e0d178b1d1e | 223 | |
wolfSSL | 16:8e0d178b1d1e | 224 | if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { |
wolfSSL | 15:117db924cf7c | 225 | WOLFSSL_MSG("Unexpected tag in PKCS12 DER"); |
wolfSSL | 15:117db924cf7c | 226 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 227 | return ASN_PARSE_E; |
wolfSSL | 15:117db924cf7c | 228 | } |
wolfSSL | 15:117db924cf7c | 229 | if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { |
wolfSSL | 15:117db924cf7c | 230 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 231 | return ret; |
wolfSSL | 15:117db924cf7c | 232 | } |
wolfSSL | 15:117db924cf7c | 233 | |
wolfSSL | 15:117db924cf7c | 234 | switch (oid) { |
wolfSSL | 15:117db924cf7c | 235 | case WC_PKCS12_ENCRYPTED_DATA: |
wolfSSL | 15:117db924cf7c | 236 | WOLFSSL_MSG("Found PKCS12 OBJECT: ENCRYPTED DATA\n"); |
wolfSSL | 15:117db924cf7c | 237 | break; |
wolfSSL | 15:117db924cf7c | 238 | |
wolfSSL | 15:117db924cf7c | 239 | case WC_PKCS12_DATA: |
wolfSSL | 15:117db924cf7c | 240 | WOLFSSL_MSG("Found PKCS12 OBJECT: DATA"); |
wolfSSL | 15:117db924cf7c | 241 | /* get octets holding contents */ |
wolfSSL | 16:8e0d178b1d1e | 242 | if (GetASNTag(input, &localIdx, &tag, maxIdx) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 243 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 16:8e0d178b1d1e | 244 | return ASN_PARSE_E; |
wolfSSL | 16:8e0d178b1d1e | 245 | } |
wolfSSL | 16:8e0d178b1d1e | 246 | |
wolfSSL | 16:8e0d178b1d1e | 247 | if (tag != ASN_OCTET_STRING) { |
wolfSSL | 15:117db924cf7c | 248 | WOLFSSL_MSG("Wrong tag with content PKCS12 type DATA"); |
wolfSSL | 15:117db924cf7c | 249 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 250 | return ASN_PARSE_E; |
wolfSSL | 15:117db924cf7c | 251 | } |
wolfSSL | 15:117db924cf7c | 252 | if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { |
wolfSSL | 15:117db924cf7c | 253 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 254 | return ret; |
wolfSSL | 15:117db924cf7c | 255 | } |
wolfSSL | 15:117db924cf7c | 256 | |
wolfSSL | 15:117db924cf7c | 257 | break; |
wolfSSL | 15:117db924cf7c | 258 | } |
wolfSSL | 15:117db924cf7c | 259 | |
wolfSSL | 15:117db924cf7c | 260 | safe->dataSz = size; |
wolfSSL | 15:117db924cf7c | 261 | safe->data = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 262 | if (safe->data == NULL) { |
wolfSSL | 15:117db924cf7c | 263 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 264 | return MEMORY_E; |
wolfSSL | 15:117db924cf7c | 265 | } |
wolfSSL | 15:117db924cf7c | 266 | XMEMCPY(safe->data, input + localIdx, size); |
wolfSSL | 15:117db924cf7c | 267 | *idx = localIdx; |
wolfSSL | 15:117db924cf7c | 268 | |
wolfSSL | 15:117db924cf7c | 269 | /* an instance of AuthenticatedSafe is created from |
wolfSSL | 16:8e0d178b1d1e | 270 | * ContentInfo's strung together in a SEQUENCE. Here we iterate |
wolfSSL | 15:117db924cf7c | 271 | * through the ContentInfo's and add them to our |
wolfSSL | 15:117db924cf7c | 272 | * AuthenticatedSafe struct */ |
wolfSSL | 15:117db924cf7c | 273 | localIdx = 0; |
wolfSSL | 15:117db924cf7c | 274 | input = safe->data; |
wolfSSL | 15:117db924cf7c | 275 | { |
wolfSSL | 15:117db924cf7c | 276 | int CISz; |
wolfSSL | 15:117db924cf7c | 277 | ret = GetSequence(input, &localIdx, &CISz, safe->dataSz); |
wolfSSL | 15:117db924cf7c | 278 | if (ret < 0) { |
wolfSSL | 15:117db924cf7c | 279 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 280 | return ASN_PARSE_E; |
wolfSSL | 15:117db924cf7c | 281 | } |
wolfSSL | 15:117db924cf7c | 282 | CISz += localIdx; |
wolfSSL | 15:117db924cf7c | 283 | while ((int)localIdx < CISz) { |
wolfSSL | 15:117db924cf7c | 284 | int curSz = 0; |
wolfSSL | 15:117db924cf7c | 285 | word32 curIdx; |
wolfSSL | 15:117db924cf7c | 286 | ContentInfo* ci = NULL; |
wolfSSL | 15:117db924cf7c | 287 | |
wolfSSL | 15:117db924cf7c | 288 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 289 | printf("\t\tlooking for Content Info.... "); |
wolfSSL | 15:117db924cf7c | 290 | #endif |
wolfSSL | 15:117db924cf7c | 291 | |
wolfSSL | 15:117db924cf7c | 292 | if ((ret = GetSequence(input, &localIdx, &curSz, safe->dataSz)) |
wolfSSL | 15:117db924cf7c | 293 | < 0) { |
wolfSSL | 15:117db924cf7c | 294 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 295 | return ret; |
wolfSSL | 15:117db924cf7c | 296 | } |
wolfSSL | 15:117db924cf7c | 297 | |
wolfSSL | 15:117db924cf7c | 298 | if (curSz > CISz) { |
wolfSSL | 15:117db924cf7c | 299 | /* subset should not be larger than universe */ |
wolfSSL | 15:117db924cf7c | 300 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 301 | return ASN_PARSE_E; |
wolfSSL | 15:117db924cf7c | 302 | } |
wolfSSL | 15:117db924cf7c | 303 | |
wolfSSL | 15:117db924cf7c | 304 | curIdx = localIdx; |
wolfSSL | 15:117db924cf7c | 305 | if ((ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, |
wolfSSL | 15:117db924cf7c | 306 | safe->dataSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 307 | WOLFSSL_LEAVE("Get object id failed", ret); |
wolfSSL | 15:117db924cf7c | 308 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 309 | return ret; |
wolfSSL | 15:117db924cf7c | 310 | } |
wolfSSL | 15:117db924cf7c | 311 | |
wolfSSL | 15:117db924cf7c | 312 | /* create new content info struct ... possible OID sanity check? */ |
wolfSSL | 15:117db924cf7c | 313 | ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), pkcs12->heap, |
wolfSSL | 15:117db924cf7c | 314 | DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 315 | if (ci == NULL) { |
wolfSSL | 15:117db924cf7c | 316 | freeSafe(safe, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 317 | return MEMORY_E; |
wolfSSL | 15:117db924cf7c | 318 | } |
wolfSSL | 15:117db924cf7c | 319 | |
wolfSSL | 15:117db924cf7c | 320 | ci->type = oid; |
wolfSSL | 15:117db924cf7c | 321 | ci->dataSz = curSz - (localIdx-curIdx); |
wolfSSL | 15:117db924cf7c | 322 | ci->data = (byte*)input + localIdx; |
wolfSSL | 15:117db924cf7c | 323 | localIdx += ci->dataSz; |
wolfSSL | 15:117db924cf7c | 324 | |
wolfSSL | 15:117db924cf7c | 325 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 326 | switch (oid) { |
wolfSSL | 15:117db924cf7c | 327 | case WC_PKCS12_ENCRYPTED_DATA: |
wolfSSL | 15:117db924cf7c | 328 | printf("CONTENT INFO: ENCRYPTED DATA, size = %d\n", ci->dataSz); |
wolfSSL | 15:117db924cf7c | 329 | break; |
wolfSSL | 15:117db924cf7c | 330 | |
wolfSSL | 15:117db924cf7c | 331 | case WC_PKCS12_DATA: |
wolfSSL | 15:117db924cf7c | 332 | printf("CONTENT INFO: DATA, size = %d\n", ci->dataSz); |
wolfSSL | 15:117db924cf7c | 333 | break; |
wolfSSL | 15:117db924cf7c | 334 | default: |
wolfSSL | 15:117db924cf7c | 335 | printf("CONTENT INFO: UNKNOWN, size = %d\n", ci->dataSz); |
wolfSSL | 15:117db924cf7c | 336 | } |
wolfSSL | 15:117db924cf7c | 337 | #endif |
wolfSSL | 15:117db924cf7c | 338 | |
wolfSSL | 15:117db924cf7c | 339 | /* insert to head of list */ |
wolfSSL | 15:117db924cf7c | 340 | ci->next = safe->CI; |
wolfSSL | 15:117db924cf7c | 341 | safe->CI = ci; |
wolfSSL | 15:117db924cf7c | 342 | safe->numCI += 1; |
wolfSSL | 15:117db924cf7c | 343 | } |
wolfSSL | 15:117db924cf7c | 344 | } |
wolfSSL | 15:117db924cf7c | 345 | |
wolfSSL | 15:117db924cf7c | 346 | pkcs12->safe = safe; |
wolfSSL | 15:117db924cf7c | 347 | *idx += localIdx; |
wolfSSL | 15:117db924cf7c | 348 | |
wolfSSL | 15:117db924cf7c | 349 | return ret; |
wolfSSL | 15:117db924cf7c | 350 | } |
wolfSSL | 15:117db924cf7c | 351 | |
wolfSSL | 15:117db924cf7c | 352 | |
wolfSSL | 15:117db924cf7c | 353 | /* optional mac data */ |
wolfSSL | 15:117db924cf7c | 354 | static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, |
wolfSSL | 15:117db924cf7c | 355 | word32 totalSz) |
wolfSSL | 15:117db924cf7c | 356 | { |
wolfSSL | 15:117db924cf7c | 357 | MacData* mac; |
wolfSSL | 15:117db924cf7c | 358 | word32 curIdx = *idx; |
wolfSSL | 15:117db924cf7c | 359 | word32 oid = 0; |
wolfSSL | 15:117db924cf7c | 360 | int size, ret; |
wolfSSL | 16:8e0d178b1d1e | 361 | byte tag; |
wolfSSL | 15:117db924cf7c | 362 | |
wolfSSL | 15:117db924cf7c | 363 | /* Digest Info : Sequence |
wolfSSL | 15:117db924cf7c | 364 | * DigestAlgorithmIdentifier |
wolfSSL | 15:117db924cf7c | 365 | * Digest |
wolfSSL | 15:117db924cf7c | 366 | */ |
wolfSSL | 15:117db924cf7c | 367 | if ((ret = GetSequence(mem, &curIdx, &size, totalSz)) <= 0) { |
wolfSSL | 15:117db924cf7c | 368 | WOLFSSL_MSG("Failed to get PKCS12 sequence"); |
wolfSSL | 15:117db924cf7c | 369 | return ret; |
wolfSSL | 15:117db924cf7c | 370 | } |
wolfSSL | 15:117db924cf7c | 371 | |
wolfSSL | 15:117db924cf7c | 372 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 373 | printf("\t\tSEQUENCE: DigestInfo size = %d\n", size); |
wolfSSL | 15:117db924cf7c | 374 | #endif |
wolfSSL | 15:117db924cf7c | 375 | |
wolfSSL | 15:117db924cf7c | 376 | mac = (MacData*)XMALLOC(sizeof(MacData), pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 377 | if (mac == NULL) { |
wolfSSL | 15:117db924cf7c | 378 | return MEMORY_E; |
wolfSSL | 15:117db924cf7c | 379 | } |
wolfSSL | 15:117db924cf7c | 380 | XMEMSET(mac, 0, sizeof(MacData)); |
wolfSSL | 15:117db924cf7c | 381 | |
wolfSSL | 15:117db924cf7c | 382 | /* DigestAlgorithmIdentifier */ |
wolfSSL | 15:117db924cf7c | 383 | if ((ret = GetAlgoId(mem, &curIdx, &oid, oidIgnoreType, totalSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 384 | WOLFSSL_MSG("Failed to get PKCS12 sequence"); |
wolfSSL | 15:117db924cf7c | 385 | XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 386 | return ret; |
wolfSSL | 15:117db924cf7c | 387 | } |
wolfSSL | 15:117db924cf7c | 388 | mac->oid = oid; |
wolfSSL | 15:117db924cf7c | 389 | |
wolfSSL | 15:117db924cf7c | 390 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 391 | printf("\t\tALGO ID = %d\n", oid); |
wolfSSL | 15:117db924cf7c | 392 | #endif |
wolfSSL | 15:117db924cf7c | 393 | |
wolfSSL | 15:117db924cf7c | 394 | /* Digest: should be octet type holding digest */ |
wolfSSL | 16:8e0d178b1d1e | 395 | if (GetASNTag(mem, &curIdx, &tag, totalSz) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 396 | XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 16:8e0d178b1d1e | 397 | return ASN_PARSE_E; |
wolfSSL | 16:8e0d178b1d1e | 398 | } |
wolfSSL | 16:8e0d178b1d1e | 399 | |
wolfSSL | 16:8e0d178b1d1e | 400 | if (tag != ASN_OCTET_STRING) { |
wolfSSL | 15:117db924cf7c | 401 | WOLFSSL_MSG("Failed to get digest"); |
wolfSSL | 15:117db924cf7c | 402 | XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 403 | return ASN_PARSE_E; |
wolfSSL | 15:117db924cf7c | 404 | } |
wolfSSL | 15:117db924cf7c | 405 | |
wolfSSL | 15:117db924cf7c | 406 | if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) { |
wolfSSL | 15:117db924cf7c | 407 | XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 408 | return ret; |
wolfSSL | 15:117db924cf7c | 409 | } |
wolfSSL | 15:117db924cf7c | 410 | mac->digestSz = size; |
wolfSSL | 15:117db924cf7c | 411 | mac->digest = (byte*)XMALLOC(mac->digestSz, pkcs12->heap, |
wolfSSL | 15:117db924cf7c | 412 | DYNAMIC_TYPE_DIGEST); |
wolfSSL | 15:117db924cf7c | 413 | if (mac->digest == NULL || mac->digestSz + curIdx > totalSz) { |
wolfSSL | 15:117db924cf7c | 414 | ERROR_OUT(MEMORY_E, exit_gsd); |
wolfSSL | 15:117db924cf7c | 415 | } |
wolfSSL | 15:117db924cf7c | 416 | XMEMCPY(mac->digest, mem + curIdx, mac->digestSz); |
wolfSSL | 15:117db924cf7c | 417 | |
wolfSSL | 15:117db924cf7c | 418 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 419 | { |
wolfSSL | 15:117db924cf7c | 420 | byte* p; |
wolfSSL | 15:117db924cf7c | 421 | for (printf("\t\tDigest = "), p = (byte*)mem+curIdx; |
wolfSSL | 15:117db924cf7c | 422 | p < (byte*)mem + curIdx + mac->digestSz; |
wolfSSL | 15:117db924cf7c | 423 | printf("%02X", *p), p++); |
wolfSSL | 15:117db924cf7c | 424 | printf(" : size = %d\n", mac->digestSz); |
wolfSSL | 15:117db924cf7c | 425 | } |
wolfSSL | 15:117db924cf7c | 426 | #endif |
wolfSSL | 15:117db924cf7c | 427 | |
wolfSSL | 15:117db924cf7c | 428 | curIdx += mac->digestSz; |
wolfSSL | 15:117db924cf7c | 429 | |
wolfSSL | 15:117db924cf7c | 430 | /* get salt, should be octet string */ |
wolfSSL | 16:8e0d178b1d1e | 431 | if (GetASNTag(mem, &curIdx, &tag, totalSz) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 432 | ERROR_OUT(ASN_PARSE_E, exit_gsd); |
wolfSSL | 16:8e0d178b1d1e | 433 | } |
wolfSSL | 16:8e0d178b1d1e | 434 | |
wolfSSL | 16:8e0d178b1d1e | 435 | if (tag != ASN_OCTET_STRING) { |
wolfSSL | 15:117db924cf7c | 436 | WOLFSSL_MSG("Failed to get salt"); |
wolfSSL | 15:117db924cf7c | 437 | ERROR_OUT(ASN_PARSE_E, exit_gsd); |
wolfSSL | 15:117db924cf7c | 438 | } |
wolfSSL | 15:117db924cf7c | 439 | |
wolfSSL | 16:8e0d178b1d1e | 440 | if ((ret = GetLength(mem, &curIdx, &size, totalSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 441 | goto exit_gsd; |
wolfSSL | 15:117db924cf7c | 442 | } |
wolfSSL | 15:117db924cf7c | 443 | mac->saltSz = size; |
wolfSSL | 15:117db924cf7c | 444 | mac->salt = (byte*)XMALLOC(mac->saltSz, pkcs12->heap, DYNAMIC_TYPE_SALT); |
wolfSSL | 15:117db924cf7c | 445 | if (mac->salt == NULL || mac->saltSz + curIdx > totalSz) { |
wolfSSL | 15:117db924cf7c | 446 | ERROR_OUT(MEMORY_E, exit_gsd); |
wolfSSL | 15:117db924cf7c | 447 | } |
wolfSSL | 15:117db924cf7c | 448 | XMEMCPY(mac->salt, mem + curIdx, mac->saltSz); |
wolfSSL | 15:117db924cf7c | 449 | |
wolfSSL | 15:117db924cf7c | 450 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 451 | { |
wolfSSL | 15:117db924cf7c | 452 | byte* p; |
wolfSSL | 15:117db924cf7c | 453 | for (printf("\t\tSalt = "), p = (byte*)mem + curIdx; |
wolfSSL | 15:117db924cf7c | 454 | p < (byte*)mem + curIdx + mac->saltSz; |
wolfSSL | 15:117db924cf7c | 455 | printf("%02X", *p), p++); |
wolfSSL | 15:117db924cf7c | 456 | printf(" : size = %d\n", mac->saltSz); |
wolfSSL | 15:117db924cf7c | 457 | } |
wolfSSL | 15:117db924cf7c | 458 | #endif |
wolfSSL | 15:117db924cf7c | 459 | |
wolfSSL | 15:117db924cf7c | 460 | curIdx += mac->saltSz; |
wolfSSL | 15:117db924cf7c | 461 | |
wolfSSL | 15:117db924cf7c | 462 | /* check for MAC iterations, default to 1 */ |
wolfSSL | 15:117db924cf7c | 463 | mac->itt = WC_PKCS12_MAC_DEFAULT; |
wolfSSL | 15:117db924cf7c | 464 | if (curIdx < totalSz) { |
wolfSSL | 15:117db924cf7c | 465 | int number = 0; |
wolfSSL | 15:117db924cf7c | 466 | if ((ret = GetShortInt(mem, &curIdx, &number, totalSz)) >= 0) { |
wolfSSL | 15:117db924cf7c | 467 | /* found a iteration value */ |
wolfSSL | 15:117db924cf7c | 468 | mac->itt = number; |
wolfSSL | 15:117db924cf7c | 469 | } |
wolfSSL | 15:117db924cf7c | 470 | } |
wolfSSL | 15:117db924cf7c | 471 | |
wolfSSL | 15:117db924cf7c | 472 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 16:8e0d178b1d1e | 473 | printf("\t\tITERATIONS : %d\n", mac->itt); |
wolfSSL | 15:117db924cf7c | 474 | #endif |
wolfSSL | 15:117db924cf7c | 475 | |
wolfSSL | 15:117db924cf7c | 476 | *idx = curIdx; |
wolfSSL | 15:117db924cf7c | 477 | pkcs12->signData = mac; |
wolfSSL | 15:117db924cf7c | 478 | ret = 0; /* success */ |
wolfSSL | 15:117db924cf7c | 479 | |
wolfSSL | 15:117db924cf7c | 480 | exit_gsd: |
wolfSSL | 15:117db924cf7c | 481 | |
wolfSSL | 15:117db924cf7c | 482 | /* failure cleanup */ |
wolfSSL | 15:117db924cf7c | 483 | if (ret != 0) { |
wolfSSL | 15:117db924cf7c | 484 | if (mac) { |
wolfSSL | 15:117db924cf7c | 485 | if (mac->digest) |
wolfSSL | 15:117db924cf7c | 486 | XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_DIGEST); |
wolfSSL | 15:117db924cf7c | 487 | XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 488 | } |
wolfSSL | 15:117db924cf7c | 489 | } |
wolfSSL | 15:117db924cf7c | 490 | |
wolfSSL | 15:117db924cf7c | 491 | return ret; |
wolfSSL | 15:117db924cf7c | 492 | } |
wolfSSL | 15:117db924cf7c | 493 | |
wolfSSL | 15:117db924cf7c | 494 | |
wolfSSL | 15:117db924cf7c | 495 | /* expects PKCS12 signData to be set up with OID |
wolfSSL | 15:117db924cf7c | 496 | * |
wolfSSL | 15:117db924cf7c | 497 | * returns the size of mac created on success. A negative value will be returned |
wolfSSL | 15:117db924cf7c | 498 | * in the case that an error happened. |
wolfSSL | 15:117db924cf7c | 499 | */ |
wolfSSL | 15:117db924cf7c | 500 | static int wc_PKCS12_create_mac(WC_PKCS12* pkcs12, byte* data, word32 dataSz, |
wolfSSL | 15:117db924cf7c | 501 | const byte* psw, word32 pswSz, byte* out, word32 outSz) |
wolfSSL | 15:117db924cf7c | 502 | { |
wolfSSL | 15:117db924cf7c | 503 | Hmac hmac; |
wolfSSL | 15:117db924cf7c | 504 | MacData* mac; |
wolfSSL | 15:117db924cf7c | 505 | int ret, kLen; |
wolfSSL | 15:117db924cf7c | 506 | enum wc_HashType hashT; |
wolfSSL | 15:117db924cf7c | 507 | int idx = 0; |
wolfSSL | 15:117db924cf7c | 508 | int id = 3; /* value from RFC 7292 indicating key is used for MAC */ |
wolfSSL | 15:117db924cf7c | 509 | word32 i; |
wolfSSL | 15:117db924cf7c | 510 | byte unicodePasswd[MAX_UNICODE_SZ]; |
wolfSSL | 15:117db924cf7c | 511 | byte key[MAX_KEY_SIZE]; |
wolfSSL | 15:117db924cf7c | 512 | |
wolfSSL | 15:117db924cf7c | 513 | if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL || |
wolfSSL | 15:117db924cf7c | 514 | out == NULL) { |
wolfSSL | 15:117db924cf7c | 515 | return BAD_FUNC_ARG; |
wolfSSL | 15:117db924cf7c | 516 | } |
wolfSSL | 15:117db924cf7c | 517 | |
wolfSSL | 15:117db924cf7c | 518 | mac = pkcs12->signData; |
wolfSSL | 15:117db924cf7c | 519 | |
wolfSSL | 15:117db924cf7c | 520 | /* unicode set up from asn.c */ |
wolfSSL | 15:117db924cf7c | 521 | if ((pswSz * 2 + 2) > (int)sizeof(unicodePasswd)) { |
wolfSSL | 15:117db924cf7c | 522 | WOLFSSL_MSG("PKCS12 max unicode size too small"); |
wolfSSL | 15:117db924cf7c | 523 | return UNICODE_SIZE_E; |
wolfSSL | 15:117db924cf7c | 524 | } |
wolfSSL | 15:117db924cf7c | 525 | |
wolfSSL | 15:117db924cf7c | 526 | for (i = 0; i < pswSz; i++) { |
wolfSSL | 15:117db924cf7c | 527 | unicodePasswd[idx++] = 0x00; |
wolfSSL | 15:117db924cf7c | 528 | unicodePasswd[idx++] = (byte)psw[i]; |
wolfSSL | 15:117db924cf7c | 529 | } |
wolfSSL | 15:117db924cf7c | 530 | /* add trailing NULL */ |
wolfSSL | 15:117db924cf7c | 531 | unicodePasswd[idx++] = 0x00; |
wolfSSL | 15:117db924cf7c | 532 | unicodePasswd[idx++] = 0x00; |
wolfSSL | 15:117db924cf7c | 533 | |
wolfSSL | 15:117db924cf7c | 534 | /* get hash type used and resulting size of HMAC key */ |
wolfSSL | 15:117db924cf7c | 535 | hashT = wc_OidGetHash(mac->oid); |
wolfSSL | 15:117db924cf7c | 536 | if (hashT == WC_HASH_TYPE_NONE) { |
wolfSSL | 15:117db924cf7c | 537 | WOLFSSL_MSG("Unsupported hash used"); |
wolfSSL | 15:117db924cf7c | 538 | return BAD_FUNC_ARG; |
wolfSSL | 15:117db924cf7c | 539 | } |
wolfSSL | 15:117db924cf7c | 540 | kLen = wc_HashGetDigestSize(hashT); |
wolfSSL | 15:117db924cf7c | 541 | |
wolfSSL | 15:117db924cf7c | 542 | /* check out buffer is large enough */ |
wolfSSL | 15:117db924cf7c | 543 | if (kLen < 0 || outSz < (word32)kLen) { |
wolfSSL | 15:117db924cf7c | 544 | return BAD_FUNC_ARG; |
wolfSSL | 15:117db924cf7c | 545 | } |
wolfSSL | 15:117db924cf7c | 546 | |
wolfSSL | 15:117db924cf7c | 547 | /* idx contains size of unicodePasswd */ |
wolfSSL | 15:117db924cf7c | 548 | if ((ret = wc_PKCS12_PBKDF_ex(key, unicodePasswd, idx, mac->salt, |
wolfSSL | 15:117db924cf7c | 549 | mac->saltSz, mac->itt, kLen, (int)hashT, id, pkcs12->heap)) < 0) { |
wolfSSL | 15:117db924cf7c | 550 | return ret; |
wolfSSL | 15:117db924cf7c | 551 | } |
wolfSSL | 15:117db924cf7c | 552 | |
wolfSSL | 15:117db924cf7c | 553 | /* now that key has been created use it to get HMAC hash on data */ |
wolfSSL | 15:117db924cf7c | 554 | if ((ret = wc_HmacInit(&hmac, pkcs12->heap, INVALID_DEVID)) != 0) { |
wolfSSL | 15:117db924cf7c | 555 | return ret; |
wolfSSL | 15:117db924cf7c | 556 | } |
wolfSSL | 15:117db924cf7c | 557 | ret = wc_HmacSetKey(&hmac, (int)hashT, key, kLen); |
wolfSSL | 15:117db924cf7c | 558 | if (ret == 0) |
wolfSSL | 15:117db924cf7c | 559 | ret = wc_HmacUpdate(&hmac, data, dataSz); |
wolfSSL | 15:117db924cf7c | 560 | if (ret == 0) |
wolfSSL | 15:117db924cf7c | 561 | ret = wc_HmacFinal(&hmac, out); |
wolfSSL | 15:117db924cf7c | 562 | wc_HmacFree(&hmac); |
wolfSSL | 15:117db924cf7c | 563 | |
wolfSSL | 15:117db924cf7c | 564 | if (ret != 0) |
wolfSSL | 15:117db924cf7c | 565 | return ret; |
wolfSSL | 15:117db924cf7c | 566 | |
wolfSSL | 15:117db924cf7c | 567 | return kLen; /* same as digest size */ |
wolfSSL | 15:117db924cf7c | 568 | } |
wolfSSL | 15:117db924cf7c | 569 | |
wolfSSL | 15:117db924cf7c | 570 | |
wolfSSL | 15:117db924cf7c | 571 | /* check mac on pkcs12, pkcs12->mac has been sanity checked before entering * |
wolfSSL | 15:117db924cf7c | 572 | * returns the result of comparison, success is 0 */ |
wolfSSL | 15:117db924cf7c | 573 | static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz, |
wolfSSL | 15:117db924cf7c | 574 | const byte* psw, word32 pswSz) |
wolfSSL | 15:117db924cf7c | 575 | { |
wolfSSL | 15:117db924cf7c | 576 | MacData* mac; |
wolfSSL | 15:117db924cf7c | 577 | int ret; |
wolfSSL | 15:117db924cf7c | 578 | byte digest[WC_MAX_DIGEST_SIZE]; |
wolfSSL | 15:117db924cf7c | 579 | |
wolfSSL | 15:117db924cf7c | 580 | if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL) { |
wolfSSL | 15:117db924cf7c | 581 | return BAD_FUNC_ARG; |
wolfSSL | 15:117db924cf7c | 582 | } |
wolfSSL | 15:117db924cf7c | 583 | |
wolfSSL | 15:117db924cf7c | 584 | mac = pkcs12->signData; |
wolfSSL | 15:117db924cf7c | 585 | |
wolfSSL | 15:117db924cf7c | 586 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 587 | printf("Verifying MAC with OID = %d\n", mac->oid); |
wolfSSL | 15:117db924cf7c | 588 | #endif |
wolfSSL | 15:117db924cf7c | 589 | |
wolfSSL | 15:117db924cf7c | 590 | /* check if this builds digest size is too small */ |
wolfSSL | 15:117db924cf7c | 591 | if (mac->digestSz > WC_MAX_DIGEST_SIZE) { |
wolfSSL | 15:117db924cf7c | 592 | WOLFSSL_MSG("PKCS12 max digest size too small"); |
wolfSSL | 15:117db924cf7c | 593 | return BAD_FUNC_ARG; |
wolfSSL | 15:117db924cf7c | 594 | } |
wolfSSL | 15:117db924cf7c | 595 | |
wolfSSL | 15:117db924cf7c | 596 | if ((ret = wc_PKCS12_create_mac(pkcs12, data, dataSz, psw, pswSz, |
wolfSSL | 15:117db924cf7c | 597 | digest, WC_MAX_DIGEST_SIZE)) < 0) { |
wolfSSL | 15:117db924cf7c | 598 | return ret; |
wolfSSL | 15:117db924cf7c | 599 | } |
wolfSSL | 15:117db924cf7c | 600 | |
wolfSSL | 15:117db924cf7c | 601 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 602 | { |
wolfSSL | 15:117db924cf7c | 603 | byte* p; |
wolfSSL | 15:117db924cf7c | 604 | for (printf("\t\tHash = "), p = (byte*)digest; |
wolfSSL | 15:117db924cf7c | 605 | p < (byte*)digest + mac->digestSz; |
wolfSSL | 15:117db924cf7c | 606 | printf("%02X", *p), p++); |
wolfSSL | 15:117db924cf7c | 607 | printf(" : size = %d\n", mac->digestSz); |
wolfSSL | 15:117db924cf7c | 608 | } |
wolfSSL | 15:117db924cf7c | 609 | #endif |
wolfSSL | 15:117db924cf7c | 610 | |
wolfSSL | 15:117db924cf7c | 611 | return XMEMCMP(digest, mac->digest, mac->digestSz); |
wolfSSL | 15:117db924cf7c | 612 | } |
wolfSSL | 15:117db924cf7c | 613 | |
wolfSSL | 15:117db924cf7c | 614 | |
wolfSSL | 15:117db924cf7c | 615 | /* Convert DER format stored in der buffer to WC_PKCS12 struct |
wolfSSL | 16:8e0d178b1d1e | 616 | * Puts the raw contents of Content Info into structure without completely |
wolfSSL | 15:117db924cf7c | 617 | * parsing or decoding. |
wolfSSL | 15:117db924cf7c | 618 | * der : pointer to der buffer holding PKCS12 |
wolfSSL | 15:117db924cf7c | 619 | * derSz : size of der buffer |
wolfSSL | 15:117db924cf7c | 620 | * pkcs12 : non-null pkcs12 pointer |
wolfSSL | 15:117db924cf7c | 621 | * return 0 on success and negative on failure. |
wolfSSL | 15:117db924cf7c | 622 | */ |
wolfSSL | 15:117db924cf7c | 623 | int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12) |
wolfSSL | 15:117db924cf7c | 624 | { |
wolfSSL | 15:117db924cf7c | 625 | word32 idx = 0; |
wolfSSL | 15:117db924cf7c | 626 | word32 totalSz = 0; |
wolfSSL | 15:117db924cf7c | 627 | int ret; |
wolfSSL | 15:117db924cf7c | 628 | int size = 0; |
wolfSSL | 15:117db924cf7c | 629 | int version = 0; |
wolfSSL | 15:117db924cf7c | 630 | |
wolfSSL | 15:117db924cf7c | 631 | WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio"); |
wolfSSL | 15:117db924cf7c | 632 | |
wolfSSL | 15:117db924cf7c | 633 | if (der == NULL || pkcs12 == NULL) { |
wolfSSL | 15:117db924cf7c | 634 | return BAD_FUNC_ARG; |
wolfSSL | 15:117db924cf7c | 635 | } |
wolfSSL | 15:117db924cf7c | 636 | |
wolfSSL | 15:117db924cf7c | 637 | totalSz = derSz; |
wolfSSL | 15:117db924cf7c | 638 | if ((ret = GetSequence(der, &idx, &size, totalSz)) <= 0) { |
wolfSSL | 15:117db924cf7c | 639 | WOLFSSL_MSG("Failed to get PKCS12 sequence"); |
wolfSSL | 15:117db924cf7c | 640 | return ret; |
wolfSSL | 15:117db924cf7c | 641 | } |
wolfSSL | 15:117db924cf7c | 642 | |
wolfSSL | 15:117db924cf7c | 643 | /* get version */ |
wolfSSL | 15:117db924cf7c | 644 | if ((ret = GetMyVersion(der, &idx, &version, totalSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 645 | return ret; |
wolfSSL | 15:117db924cf7c | 646 | } |
wolfSSL | 15:117db924cf7c | 647 | |
wolfSSL | 15:117db924cf7c | 648 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 649 | printf("\nBEGIN: PKCS12 size = %d\n", totalSz); |
wolfSSL | 15:117db924cf7c | 650 | printf("version = %d\n", version); |
wolfSSL | 15:117db924cf7c | 651 | #endif |
wolfSSL | 15:117db924cf7c | 652 | |
wolfSSL | 16:8e0d178b1d1e | 653 | if (version != WC_PKCS12_VERSION_DEFAULT) { |
wolfSSL | 15:117db924cf7c | 654 | WOLFSSL_MSG("PKCS12 unsupported version!"); |
wolfSSL | 15:117db924cf7c | 655 | return ASN_VERSION_E; |
wolfSSL | 15:117db924cf7c | 656 | } |
wolfSSL | 15:117db924cf7c | 657 | |
wolfSSL | 15:117db924cf7c | 658 | if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 659 | return ret; |
wolfSSL | 15:117db924cf7c | 660 | } |
wolfSSL | 15:117db924cf7c | 661 | |
wolfSSL | 15:117db924cf7c | 662 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 663 | printf("\tSEQUENCE: AuthenticatedSafe size = %d\n", size); |
wolfSSL | 15:117db924cf7c | 664 | #endif |
wolfSSL | 15:117db924cf7c | 665 | |
wolfSSL | 15:117db924cf7c | 666 | if ((ret = GetSafeContent(pkcs12, der, &idx, size + idx)) < 0) { |
wolfSSL | 15:117db924cf7c | 667 | WOLFSSL_MSG("GetSafeContent error"); |
wolfSSL | 15:117db924cf7c | 668 | return ret; |
wolfSSL | 15:117db924cf7c | 669 | } |
wolfSSL | 15:117db924cf7c | 670 | |
wolfSSL | 15:117db924cf7c | 671 | /* if more buffer left check for MAC data */ |
wolfSSL | 15:117db924cf7c | 672 | if (idx < totalSz) { |
wolfSSL | 15:117db924cf7c | 673 | if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 674 | WOLFSSL_MSG("Ignoring unknown data at end of PKCS12 DER buffer"); |
wolfSSL | 15:117db924cf7c | 675 | } |
wolfSSL | 15:117db924cf7c | 676 | else { |
wolfSSL | 15:117db924cf7c | 677 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 678 | printf("\tSEQUENCE: Signature size = %d\n", size); |
wolfSSL | 15:117db924cf7c | 679 | #endif |
wolfSSL | 15:117db924cf7c | 680 | |
wolfSSL | 15:117db924cf7c | 681 | if ((ret = GetSignData(pkcs12, der, &idx, totalSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 682 | return ASN_PARSE_E; |
wolfSSL | 15:117db924cf7c | 683 | } |
wolfSSL | 15:117db924cf7c | 684 | } |
wolfSSL | 15:117db924cf7c | 685 | } |
wolfSSL | 15:117db924cf7c | 686 | |
wolfSSL | 15:117db924cf7c | 687 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 688 | printf("END: PKCS12\n"); |
wolfSSL | 15:117db924cf7c | 689 | #endif |
wolfSSL | 15:117db924cf7c | 690 | |
wolfSSL | 15:117db924cf7c | 691 | return ret; |
wolfSSL | 15:117db924cf7c | 692 | } |
wolfSSL | 15:117db924cf7c | 693 | |
wolfSSL | 16:8e0d178b1d1e | 694 | /* Convert WC_PKCS12 struct to allocated DER buffer. |
wolfSSL | 16:8e0d178b1d1e | 695 | * pkcs12 : non-null pkcs12 pointer |
wolfSSL | 16:8e0d178b1d1e | 696 | * der : pointer-pointer to der buffer. If NULL space will be |
wolfSSL | 16:8e0d178b1d1e | 697 | * allocated for der, which must be freed by application. |
wolfSSL | 16:8e0d178b1d1e | 698 | * derSz : size of buffer passed in when der is not NULL. NULL arg disables |
wolfSSL | 16:8e0d178b1d1e | 699 | * sanity checks on buffer read/writes. Max size gets set to derSz when |
wolfSSL | 16:8e0d178b1d1e | 700 | * the "der" buffer passed in is NULL and LENGTH_ONLY_E is returned. |
wolfSSL | 16:8e0d178b1d1e | 701 | * return size of DER on success and negative on failure. |
wolfSSL | 16:8e0d178b1d1e | 702 | */ |
wolfSSL | 16:8e0d178b1d1e | 703 | int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz) |
wolfSSL | 16:8e0d178b1d1e | 704 | { |
wolfSSL | 16:8e0d178b1d1e | 705 | int ret = 0; |
wolfSSL | 16:8e0d178b1d1e | 706 | word32 seqSz = 0, verSz = 0, totalSz = 0, idx = 0, sdBufSz = 0; |
wolfSSL | 16:8e0d178b1d1e | 707 | byte *buf = NULL; |
wolfSSL | 16:8e0d178b1d1e | 708 | byte ver[MAX_VERSION_SZ]; |
wolfSSL | 16:8e0d178b1d1e | 709 | byte seq[MAX_SEQ_SZ]; |
wolfSSL | 16:8e0d178b1d1e | 710 | byte *sdBuf = NULL; |
wolfSSL | 16:8e0d178b1d1e | 711 | |
wolfSSL | 16:8e0d178b1d1e | 712 | if ((pkcs12 == NULL) || (pkcs12->safe == NULL) || |
wolfSSL | 16:8e0d178b1d1e | 713 | (der == NULL && derSz == NULL)) { |
wolfSSL | 16:8e0d178b1d1e | 714 | return BAD_FUNC_ARG; |
wolfSSL | 16:8e0d178b1d1e | 715 | } |
wolfSSL | 16:8e0d178b1d1e | 716 | |
wolfSSL | 16:8e0d178b1d1e | 717 | /* Create the MAC portion */ |
wolfSSL | 16:8e0d178b1d1e | 718 | if (pkcs12->signData != NULL) { |
wolfSSL | 16:8e0d178b1d1e | 719 | MacData *mac = (MacData*)pkcs12->signData; |
wolfSSL | 16:8e0d178b1d1e | 720 | word32 innerSz = 0; |
wolfSSL | 16:8e0d178b1d1e | 721 | word32 outerSz = 0; |
wolfSSL | 16:8e0d178b1d1e | 722 | |
wolfSSL | 16:8e0d178b1d1e | 723 | /* get exact size */ |
wolfSSL | 16:8e0d178b1d1e | 724 | { |
wolfSSL | 16:8e0d178b1d1e | 725 | byte ASNLENGTH[MAX_LENGTH_SZ]; |
wolfSSL | 16:8e0d178b1d1e | 726 | byte ASNSHORT[MAX_SHORT_SZ]; |
wolfSSL | 16:8e0d178b1d1e | 727 | byte ASNALGO[MAX_ALGO_SZ]; |
wolfSSL | 16:8e0d178b1d1e | 728 | word32 tmpIdx = 0; |
wolfSSL | 16:8e0d178b1d1e | 729 | |
wolfSSL | 16:8e0d178b1d1e | 730 | /* algo id */ |
wolfSSL | 16:8e0d178b1d1e | 731 | innerSz += SetAlgoID(mac->oid, ASNALGO, oidHashType, 0); |
wolfSSL | 16:8e0d178b1d1e | 732 | |
wolfSSL | 16:8e0d178b1d1e | 733 | /* Octet string holding digest */ |
wolfSSL | 16:8e0d178b1d1e | 734 | innerSz += ASN_TAG_SZ; |
wolfSSL | 16:8e0d178b1d1e | 735 | innerSz += SetLength(mac->digestSz, ASNLENGTH); |
wolfSSL | 16:8e0d178b1d1e | 736 | innerSz += mac->digestSz; |
wolfSSL | 16:8e0d178b1d1e | 737 | |
wolfSSL | 16:8e0d178b1d1e | 738 | /* salt */ |
wolfSSL | 16:8e0d178b1d1e | 739 | outerSz += ASN_TAG_SZ; |
wolfSSL | 16:8e0d178b1d1e | 740 | outerSz += SetLength(mac->saltSz, ASNLENGTH); |
wolfSSL | 16:8e0d178b1d1e | 741 | outerSz += mac->saltSz; |
wolfSSL | 16:8e0d178b1d1e | 742 | |
wolfSSL | 16:8e0d178b1d1e | 743 | /* MAC iterations */ |
wolfSSL | 16:8e0d178b1d1e | 744 | outerSz += SetShortInt(ASNSHORT, &tmpIdx, mac->itt, MAX_SHORT_SZ); |
wolfSSL | 16:8e0d178b1d1e | 745 | |
wolfSSL | 16:8e0d178b1d1e | 746 | /* sequence of inner data */ |
wolfSSL | 16:8e0d178b1d1e | 747 | outerSz += SetSequence(innerSz, seq); |
wolfSSL | 16:8e0d178b1d1e | 748 | outerSz += innerSz; |
wolfSSL | 16:8e0d178b1d1e | 749 | } |
wolfSSL | 16:8e0d178b1d1e | 750 | sdBufSz = outerSz + SetSequence(outerSz, seq); |
wolfSSL | 16:8e0d178b1d1e | 751 | sdBuf = (byte*)XMALLOC(sdBufSz, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 16:8e0d178b1d1e | 752 | if (sdBuf == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 753 | ret = MEMORY_E; |
wolfSSL | 16:8e0d178b1d1e | 754 | } |
wolfSSL | 16:8e0d178b1d1e | 755 | |
wolfSSL | 16:8e0d178b1d1e | 756 | if (ret == 0) { |
wolfSSL | 16:8e0d178b1d1e | 757 | idx += SetSequence(outerSz, sdBuf); |
wolfSSL | 16:8e0d178b1d1e | 758 | idx += SetSequence(innerSz, &sdBuf[idx]); |
wolfSSL | 16:8e0d178b1d1e | 759 | |
wolfSSL | 16:8e0d178b1d1e | 760 | /* Set Algorithm Identifier */ |
wolfSSL | 16:8e0d178b1d1e | 761 | { |
wolfSSL | 16:8e0d178b1d1e | 762 | word32 algoIdSz; |
wolfSSL | 16:8e0d178b1d1e | 763 | |
wolfSSL | 16:8e0d178b1d1e | 764 | algoIdSz = SetAlgoID(mac->oid, &sdBuf[idx], oidHashType, 0); |
wolfSSL | 16:8e0d178b1d1e | 765 | if (algoIdSz == 0) { |
wolfSSL | 16:8e0d178b1d1e | 766 | ret = ALGO_ID_E; |
wolfSSL | 16:8e0d178b1d1e | 767 | } |
wolfSSL | 16:8e0d178b1d1e | 768 | else { |
wolfSSL | 16:8e0d178b1d1e | 769 | idx += algoIdSz; |
wolfSSL | 16:8e0d178b1d1e | 770 | } |
wolfSSL | 16:8e0d178b1d1e | 771 | } |
wolfSSL | 16:8e0d178b1d1e | 772 | } |
wolfSSL | 16:8e0d178b1d1e | 773 | |
wolfSSL | 16:8e0d178b1d1e | 774 | if (ret == 0) { |
wolfSSL | 16:8e0d178b1d1e | 775 | |
wolfSSL | 16:8e0d178b1d1e | 776 | |
wolfSSL | 16:8e0d178b1d1e | 777 | /* Octet string holding digest */ |
wolfSSL | 16:8e0d178b1d1e | 778 | idx += SetOctetString(mac->digestSz, &sdBuf[idx]); |
wolfSSL | 16:8e0d178b1d1e | 779 | XMEMCPY(&sdBuf[idx], mac->digest, mac->digestSz); |
wolfSSL | 16:8e0d178b1d1e | 780 | idx += mac->digestSz; |
wolfSSL | 16:8e0d178b1d1e | 781 | |
wolfSSL | 16:8e0d178b1d1e | 782 | /* Set salt */ |
wolfSSL | 16:8e0d178b1d1e | 783 | idx += SetOctetString(mac->saltSz, &sdBuf[idx]); |
wolfSSL | 16:8e0d178b1d1e | 784 | XMEMCPY(&sdBuf[idx], mac->salt, mac->saltSz); |
wolfSSL | 16:8e0d178b1d1e | 785 | idx += mac->saltSz; |
wolfSSL | 16:8e0d178b1d1e | 786 | |
wolfSSL | 16:8e0d178b1d1e | 787 | /* MAC iterations */ |
wolfSSL | 16:8e0d178b1d1e | 788 | { |
wolfSSL | 16:8e0d178b1d1e | 789 | int tmpSz; |
wolfSSL | 16:8e0d178b1d1e | 790 | word32 tmpIdx = 0; |
wolfSSL | 16:8e0d178b1d1e | 791 | byte ar[MAX_SHORT_SZ]; |
wolfSSL | 16:8e0d178b1d1e | 792 | tmpSz = SetShortInt(ar, &tmpIdx, mac->itt, MAX_SHORT_SZ); |
wolfSSL | 16:8e0d178b1d1e | 793 | if (tmpSz < 0) { |
wolfSSL | 16:8e0d178b1d1e | 794 | ret = tmpSz; |
wolfSSL | 16:8e0d178b1d1e | 795 | } |
wolfSSL | 16:8e0d178b1d1e | 796 | else { |
wolfSSL | 16:8e0d178b1d1e | 797 | XMEMCPY(&sdBuf[idx], ar, tmpSz); |
wolfSSL | 16:8e0d178b1d1e | 798 | } |
wolfSSL | 16:8e0d178b1d1e | 799 | } |
wolfSSL | 16:8e0d178b1d1e | 800 | totalSz += sdBufSz; |
wolfSSL | 16:8e0d178b1d1e | 801 | } |
wolfSSL | 16:8e0d178b1d1e | 802 | } |
wolfSSL | 16:8e0d178b1d1e | 803 | |
wolfSSL | 16:8e0d178b1d1e | 804 | /* Calculate size of der */ |
wolfSSL | 16:8e0d178b1d1e | 805 | if (ret == 0) { |
wolfSSL | 16:8e0d178b1d1e | 806 | totalSz += pkcs12->safe->dataSz; |
wolfSSL | 16:8e0d178b1d1e | 807 | |
wolfSSL | 16:8e0d178b1d1e | 808 | totalSz += 4; /* Octet string */ |
wolfSSL | 16:8e0d178b1d1e | 809 | |
wolfSSL | 16:8e0d178b1d1e | 810 | totalSz += 4; /* Element */ |
wolfSSL | 16:8e0d178b1d1e | 811 | |
wolfSSL | 16:8e0d178b1d1e | 812 | totalSz += 2 + sizeof(WC_PKCS12_DATA_OID); |
wolfSSL | 16:8e0d178b1d1e | 813 | |
wolfSSL | 16:8e0d178b1d1e | 814 | totalSz += 4; /* Seq */ |
wolfSSL | 16:8e0d178b1d1e | 815 | |
wolfSSL | 16:8e0d178b1d1e | 816 | ret = SetMyVersion(WC_PKCS12_VERSION_DEFAULT, ver, FALSE); |
wolfSSL | 16:8e0d178b1d1e | 817 | if (ret > 0) { |
wolfSSL | 16:8e0d178b1d1e | 818 | verSz = (word32)ret; |
wolfSSL | 16:8e0d178b1d1e | 819 | ret = 0; /* value larger than 0 is success */ |
wolfSSL | 16:8e0d178b1d1e | 820 | totalSz += verSz; |
wolfSSL | 16:8e0d178b1d1e | 821 | |
wolfSSL | 16:8e0d178b1d1e | 822 | seqSz = SetSequence(totalSz, seq); |
wolfSSL | 16:8e0d178b1d1e | 823 | totalSz += seqSz; |
wolfSSL | 16:8e0d178b1d1e | 824 | |
wolfSSL | 16:8e0d178b1d1e | 825 | /* check if getting length only */ |
wolfSSL | 16:8e0d178b1d1e | 826 | if (der == NULL && derSz != NULL) { |
wolfSSL | 16:8e0d178b1d1e | 827 | *derSz = totalSz; |
wolfSSL | 16:8e0d178b1d1e | 828 | XFREE(sdBuf, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 16:8e0d178b1d1e | 829 | return LENGTH_ONLY_E; |
wolfSSL | 16:8e0d178b1d1e | 830 | } |
wolfSSL | 16:8e0d178b1d1e | 831 | |
wolfSSL | 16:8e0d178b1d1e | 832 | if (*der == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 833 | /* Allocate if requested */ |
wolfSSL | 16:8e0d178b1d1e | 834 | buf = (byte*)XMALLOC(totalSz, NULL, DYNAMIC_TYPE_PKCS); |
wolfSSL | 16:8e0d178b1d1e | 835 | } |
wolfSSL | 16:8e0d178b1d1e | 836 | else { |
wolfSSL | 16:8e0d178b1d1e | 837 | buf = *der; |
wolfSSL | 16:8e0d178b1d1e | 838 | |
wolfSSL | 16:8e0d178b1d1e | 839 | /* sanity check on buffer size if passed in */ |
wolfSSL | 16:8e0d178b1d1e | 840 | if (derSz != NULL) { |
wolfSSL | 16:8e0d178b1d1e | 841 | if (*derSz < (int)totalSz) { |
wolfSSL | 16:8e0d178b1d1e | 842 | WOLFSSL_MSG("Buffer passed in is too small"); |
wolfSSL | 16:8e0d178b1d1e | 843 | ret = BUFFER_E; |
wolfSSL | 16:8e0d178b1d1e | 844 | } |
wolfSSL | 16:8e0d178b1d1e | 845 | } |
wolfSSL | 16:8e0d178b1d1e | 846 | } |
wolfSSL | 16:8e0d178b1d1e | 847 | } |
wolfSSL | 16:8e0d178b1d1e | 848 | } |
wolfSSL | 16:8e0d178b1d1e | 849 | |
wolfSSL | 16:8e0d178b1d1e | 850 | if (buf == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 851 | ret = MEMORY_E; |
wolfSSL | 16:8e0d178b1d1e | 852 | } |
wolfSSL | 16:8e0d178b1d1e | 853 | |
wolfSSL | 16:8e0d178b1d1e | 854 | if (ret == 0) { |
wolfSSL | 16:8e0d178b1d1e | 855 | idx = 0; |
wolfSSL | 16:8e0d178b1d1e | 856 | |
wolfSSL | 16:8e0d178b1d1e | 857 | /* Copy parts to buf */ |
wolfSSL | 16:8e0d178b1d1e | 858 | XMEMCPY(&buf[idx], seq, seqSz); |
wolfSSL | 16:8e0d178b1d1e | 859 | idx += seqSz; |
wolfSSL | 16:8e0d178b1d1e | 860 | |
wolfSSL | 16:8e0d178b1d1e | 861 | XMEMCPY(&buf[idx], ver, verSz); |
wolfSSL | 16:8e0d178b1d1e | 862 | idx += verSz; |
wolfSSL | 16:8e0d178b1d1e | 863 | |
wolfSSL | 16:8e0d178b1d1e | 864 | seqSz = SetSequence(totalSz - sdBufSz - idx - 4, seq); |
wolfSSL | 16:8e0d178b1d1e | 865 | XMEMCPY(&buf[idx], seq, seqSz); |
wolfSSL | 16:8e0d178b1d1e | 866 | idx += seqSz; |
wolfSSL | 16:8e0d178b1d1e | 867 | |
wolfSSL | 16:8e0d178b1d1e | 868 | /* OID */ |
wolfSSL | 16:8e0d178b1d1e | 869 | idx += SetObjectId(sizeof(WC_PKCS12_DATA_OID), &buf[idx]); |
wolfSSL | 16:8e0d178b1d1e | 870 | XMEMCPY(&buf[idx], WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID)); |
wolfSSL | 16:8e0d178b1d1e | 871 | idx += sizeof(WC_PKCS12_DATA_OID); |
wolfSSL | 16:8e0d178b1d1e | 872 | |
wolfSSL | 16:8e0d178b1d1e | 873 | /* Element */ |
wolfSSL | 16:8e0d178b1d1e | 874 | buf[idx++] = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC; |
wolfSSL | 16:8e0d178b1d1e | 875 | idx += SetLength(totalSz - sdBufSz - idx - 3, &buf[idx]); |
wolfSSL | 16:8e0d178b1d1e | 876 | |
wolfSSL | 16:8e0d178b1d1e | 877 | /* Octet string */ |
wolfSSL | 16:8e0d178b1d1e | 878 | idx += SetOctetString(totalSz - sdBufSz - idx - 4, &buf[idx]); |
wolfSSL | 16:8e0d178b1d1e | 879 | |
wolfSSL | 16:8e0d178b1d1e | 880 | XMEMCPY(&buf[idx], pkcs12->safe->data, pkcs12->safe->dataSz); |
wolfSSL | 16:8e0d178b1d1e | 881 | idx += pkcs12->safe->dataSz; |
wolfSSL | 16:8e0d178b1d1e | 882 | |
wolfSSL | 16:8e0d178b1d1e | 883 | if (pkcs12->signData != NULL) { |
wolfSSL | 16:8e0d178b1d1e | 884 | XMEMCPY(&buf[idx], sdBuf, sdBufSz); |
wolfSSL | 16:8e0d178b1d1e | 885 | } |
wolfSSL | 16:8e0d178b1d1e | 886 | |
wolfSSL | 16:8e0d178b1d1e | 887 | if (*der == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 888 | /* Point to start of data allocated for DER */ |
wolfSSL | 16:8e0d178b1d1e | 889 | *der = buf; |
wolfSSL | 16:8e0d178b1d1e | 890 | } |
wolfSSL | 16:8e0d178b1d1e | 891 | else { |
wolfSSL | 16:8e0d178b1d1e | 892 | /* Increment pointer to byte past DER */ |
wolfSSL | 16:8e0d178b1d1e | 893 | *der = &buf[totalSz]; |
wolfSSL | 16:8e0d178b1d1e | 894 | } |
wolfSSL | 16:8e0d178b1d1e | 895 | |
wolfSSL | 16:8e0d178b1d1e | 896 | /* Return size of der */ |
wolfSSL | 16:8e0d178b1d1e | 897 | ret = totalSz; |
wolfSSL | 16:8e0d178b1d1e | 898 | } |
wolfSSL | 16:8e0d178b1d1e | 899 | |
wolfSSL | 16:8e0d178b1d1e | 900 | XFREE(sdBuf, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 16:8e0d178b1d1e | 901 | /* Allocation of buf was the last time ret could be a failure, |
wolfSSL | 16:8e0d178b1d1e | 902 | * so no need to free here */ |
wolfSSL | 16:8e0d178b1d1e | 903 | |
wolfSSL | 16:8e0d178b1d1e | 904 | return ret; |
wolfSSL | 16:8e0d178b1d1e | 905 | } |
wolfSSL | 16:8e0d178b1d1e | 906 | |
wolfSSL | 15:117db924cf7c | 907 | |
wolfSSL | 15:117db924cf7c | 908 | /* helper function to free WC_DerCertList */ |
wolfSSL | 15:117db924cf7c | 909 | void wc_FreeCertList(WC_DerCertList* list, void* heap) |
wolfSSL | 15:117db924cf7c | 910 | { |
wolfSSL | 15:117db924cf7c | 911 | WC_DerCertList* current = list; |
wolfSSL | 15:117db924cf7c | 912 | WC_DerCertList* next; |
wolfSSL | 15:117db924cf7c | 913 | |
wolfSSL | 15:117db924cf7c | 914 | if (list == NULL) { |
wolfSSL | 15:117db924cf7c | 915 | return; |
wolfSSL | 15:117db924cf7c | 916 | } |
wolfSSL | 15:117db924cf7c | 917 | |
wolfSSL | 15:117db924cf7c | 918 | while (current != NULL) { |
wolfSSL | 15:117db924cf7c | 919 | next = current->next; |
wolfSSL | 15:117db924cf7c | 920 | if (current->buffer != NULL) { |
wolfSSL | 15:117db924cf7c | 921 | XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 922 | } |
wolfSSL | 15:117db924cf7c | 923 | XFREE(current, heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 924 | current = next; |
wolfSSL | 15:117db924cf7c | 925 | } |
wolfSSL | 15:117db924cf7c | 926 | |
wolfSSL | 15:117db924cf7c | 927 | (void)heap; |
wolfSSL | 15:117db924cf7c | 928 | } |
wolfSSL | 15:117db924cf7c | 929 | |
wolfSSL | 15:117db924cf7c | 930 | static void freeDecCertList(WC_DerCertList** list, byte** pkey, word32* pkeySz, |
wolfSSL | 15:117db924cf7c | 931 | byte** cert, word32* certSz, void* heap) |
wolfSSL | 15:117db924cf7c | 932 | { |
wolfSSL | 15:117db924cf7c | 933 | WC_DerCertList* current = *list; |
wolfSSL | 15:117db924cf7c | 934 | WC_DerCertList* previous = NULL; |
wolfSSL | 15:117db924cf7c | 935 | DecodedCert DeCert; |
wolfSSL | 15:117db924cf7c | 936 | |
wolfSSL | 15:117db924cf7c | 937 | while (current != NULL) { |
wolfSSL | 15:117db924cf7c | 938 | |
wolfSSL | 15:117db924cf7c | 939 | InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap); |
wolfSSL | 15:117db924cf7c | 940 | if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) { |
wolfSSL | 15:117db924cf7c | 941 | if (wc_CheckPrivateKey(*pkey, *pkeySz, &DeCert) == 1) { |
wolfSSL | 15:117db924cf7c | 942 | WOLFSSL_MSG("Key Pair found"); |
wolfSSL | 15:117db924cf7c | 943 | *cert = current->buffer; |
wolfSSL | 15:117db924cf7c | 944 | *certSz = current->bufferSz; |
wolfSSL | 15:117db924cf7c | 945 | |
wolfSSL | 15:117db924cf7c | 946 | if (previous == NULL) { |
wolfSSL | 15:117db924cf7c | 947 | *list = current->next; |
wolfSSL | 15:117db924cf7c | 948 | } |
wolfSSL | 15:117db924cf7c | 949 | else { |
wolfSSL | 15:117db924cf7c | 950 | previous->next = current->next; |
wolfSSL | 15:117db924cf7c | 951 | } |
wolfSSL | 15:117db924cf7c | 952 | FreeDecodedCert(&DeCert); |
wolfSSL | 15:117db924cf7c | 953 | XFREE(current, heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 954 | break; |
wolfSSL | 15:117db924cf7c | 955 | } |
wolfSSL | 15:117db924cf7c | 956 | } |
wolfSSL | 15:117db924cf7c | 957 | FreeDecodedCert(&DeCert); |
wolfSSL | 15:117db924cf7c | 958 | |
wolfSSL | 15:117db924cf7c | 959 | previous = current; |
wolfSSL | 15:117db924cf7c | 960 | current = current->next; |
wolfSSL | 15:117db924cf7c | 961 | } |
wolfSSL | 15:117db924cf7c | 962 | } |
wolfSSL | 15:117db924cf7c | 963 | |
wolfSSL | 15:117db924cf7c | 964 | |
wolfSSL | 15:117db924cf7c | 965 | /* return 0 on success and negative on failure. |
wolfSSL | 15:117db924cf7c | 966 | * By side effect returns private key, cert, and optionally ca. |
wolfSSL | 15:117db924cf7c | 967 | * Parses and decodes the parts of PKCS12 |
wolfSSL | 15:117db924cf7c | 968 | * |
wolfSSL | 15:117db924cf7c | 969 | * NOTE: can parse with USER RSA enabled but may return cert that is not the |
wolfSSL | 15:117db924cf7c | 970 | * pair for the key when using RSA key pairs. |
wolfSSL | 15:117db924cf7c | 971 | * |
wolfSSL | 15:117db924cf7c | 972 | * pkcs12 : non-null WC_PKCS12 struct |
wolfSSL | 15:117db924cf7c | 973 | * psw : password to use for PKCS12 decode |
wolfSSL | 15:117db924cf7c | 974 | * pkey : Private key returned |
wolfSSL | 15:117db924cf7c | 975 | * cert : x509 cert returned |
wolfSSL | 15:117db924cf7c | 976 | * ca : optional ca returned |
wolfSSL | 15:117db924cf7c | 977 | */ |
wolfSSL | 15:117db924cf7c | 978 | int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, |
wolfSSL | 15:117db924cf7c | 979 | byte** pkey, word32* pkeySz, byte** cert, word32* certSz, |
wolfSSL | 15:117db924cf7c | 980 | WC_DerCertList** ca) |
wolfSSL | 15:117db924cf7c | 981 | { |
wolfSSL | 15:117db924cf7c | 982 | ContentInfo* ci = NULL; |
wolfSSL | 15:117db924cf7c | 983 | WC_DerCertList* certList = NULL; |
wolfSSL | 15:117db924cf7c | 984 | WC_DerCertList* tailList = NULL; |
wolfSSL | 15:117db924cf7c | 985 | byte* buf = NULL; |
wolfSSL | 15:117db924cf7c | 986 | word32 i, oid; |
wolfSSL | 15:117db924cf7c | 987 | int ret, pswSz; |
wolfSSL | 16:8e0d178b1d1e | 988 | word32 algId; |
wolfSSL | 15:117db924cf7c | 989 | |
wolfSSL | 15:117db924cf7c | 990 | WOLFSSL_ENTER("wc_PKCS12_parse"); |
wolfSSL | 15:117db924cf7c | 991 | |
wolfSSL | 15:117db924cf7c | 992 | if (pkcs12 == NULL || psw == NULL || cert == NULL || certSz == NULL || |
wolfSSL | 15:117db924cf7c | 993 | pkey == NULL || pkeySz == NULL) { |
wolfSSL | 15:117db924cf7c | 994 | return BAD_FUNC_ARG; |
wolfSSL | 15:117db924cf7c | 995 | } |
wolfSSL | 15:117db924cf7c | 996 | |
wolfSSL | 15:117db924cf7c | 997 | pswSz = (int)XSTRLEN(psw); |
wolfSSL | 15:117db924cf7c | 998 | *cert = NULL; |
wolfSSL | 15:117db924cf7c | 999 | *pkey = NULL; |
wolfSSL | 15:117db924cf7c | 1000 | if (ca != NULL) |
wolfSSL | 15:117db924cf7c | 1001 | *ca = NULL; |
wolfSSL | 15:117db924cf7c | 1002 | |
wolfSSL | 15:117db924cf7c | 1003 | /* if there is sign data then verify the MAC */ |
wolfSSL | 15:117db924cf7c | 1004 | if (pkcs12->signData != NULL ) { |
wolfSSL | 15:117db924cf7c | 1005 | if ((ret = wc_PKCS12_verify(pkcs12, pkcs12->safe->data, |
wolfSSL | 15:117db924cf7c | 1006 | pkcs12->safe->dataSz, (byte*)psw, pswSz)) != 0) { |
wolfSSL | 15:117db924cf7c | 1007 | WOLFSSL_MSG("PKCS12 Bad MAC on verify"); |
wolfSSL | 15:117db924cf7c | 1008 | WOLFSSL_LEAVE("wc_PKCS12_parse verify ", ret); |
wolfSSL | 15:117db924cf7c | 1009 | return MAC_CMP_FAILED_E; |
wolfSSL | 15:117db924cf7c | 1010 | } |
wolfSSL | 15:117db924cf7c | 1011 | } |
wolfSSL | 15:117db924cf7c | 1012 | |
wolfSSL | 15:117db924cf7c | 1013 | if (pkcs12->safe == NULL) { |
wolfSSL | 15:117db924cf7c | 1014 | WOLFSSL_MSG("No PKCS12 safes to parse"); |
wolfSSL | 15:117db924cf7c | 1015 | return BAD_FUNC_ARG; |
wolfSSL | 15:117db924cf7c | 1016 | } |
wolfSSL | 15:117db924cf7c | 1017 | |
wolfSSL | 15:117db924cf7c | 1018 | /* Decode content infos */ |
wolfSSL | 15:117db924cf7c | 1019 | ci = pkcs12->safe->CI; |
wolfSSL | 15:117db924cf7c | 1020 | for (i = 0; i < pkcs12->safe->numCI; i++) { |
wolfSSL | 15:117db924cf7c | 1021 | byte* data; |
wolfSSL | 15:117db924cf7c | 1022 | word32 idx = 0; |
wolfSSL | 15:117db924cf7c | 1023 | int size, totalSz; |
wolfSSL | 16:8e0d178b1d1e | 1024 | byte tag; |
wolfSSL | 15:117db924cf7c | 1025 | |
wolfSSL | 15:117db924cf7c | 1026 | if (ci->type == WC_PKCS12_ENCRYPTED_DATA) { |
wolfSSL | 15:117db924cf7c | 1027 | int number; |
wolfSSL | 15:117db924cf7c | 1028 | |
wolfSSL | 15:117db924cf7c | 1029 | WOLFSSL_MSG("Decrypting PKCS12 Content Info Container"); |
wolfSSL | 15:117db924cf7c | 1030 | data = ci->data; |
wolfSSL | 16:8e0d178b1d1e | 1031 | if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 1032 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 16:8e0d178b1d1e | 1033 | } |
wolfSSL | 16:8e0d178b1d1e | 1034 | |
wolfSSL | 16:8e0d178b1d1e | 1035 | if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { |
wolfSSL | 15:117db924cf7c | 1036 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1037 | } |
wolfSSL | 15:117db924cf7c | 1038 | if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 1039 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1040 | } |
wolfSSL | 15:117db924cf7c | 1041 | |
wolfSSL | 15:117db924cf7c | 1042 | if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 1043 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1044 | } |
wolfSSL | 15:117db924cf7c | 1045 | |
wolfSSL | 15:117db924cf7c | 1046 | if ((ret = GetShortInt(data, &idx, &number, ci->dataSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 1047 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1048 | } |
wolfSSL | 15:117db924cf7c | 1049 | |
wolfSSL | 15:117db924cf7c | 1050 | if (number != 0) { |
wolfSSL | 15:117db924cf7c | 1051 | WOLFSSL_MSG("Expecting 0 for Integer with Encrypted PKCS12"); |
wolfSSL | 15:117db924cf7c | 1052 | } |
wolfSSL | 15:117db924cf7c | 1053 | |
wolfSSL | 15:117db924cf7c | 1054 | if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 1055 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1056 | } |
wolfSSL | 15:117db924cf7c | 1057 | |
wolfSSL | 15:117db924cf7c | 1058 | ret = GetObjectId(data, &idx, &oid, oidIgnoreType, ci->dataSz); |
wolfSSL | 15:117db924cf7c | 1059 | if (ret < 0 || oid != WC_PKCS12_DATA) { |
wolfSSL | 15:117db924cf7c | 1060 | WOLFSSL_MSG("Not PKCS12 DATA object or get object parse error"); |
wolfSSL | 15:117db924cf7c | 1061 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1062 | } |
wolfSSL | 15:117db924cf7c | 1063 | |
wolfSSL | 15:117db924cf7c | 1064 | /* decrypted content overwrites input buffer */ |
wolfSSL | 15:117db924cf7c | 1065 | size = ci->dataSz - idx; |
wolfSSL | 15:117db924cf7c | 1066 | buf = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 1067 | if (buf == NULL) { |
wolfSSL | 15:117db924cf7c | 1068 | ERROR_OUT(MEMORY_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1069 | } |
wolfSSL | 15:117db924cf7c | 1070 | XMEMCPY(buf, data + idx, size); |
wolfSSL | 15:117db924cf7c | 1071 | |
wolfSSL | 15:117db924cf7c | 1072 | if ((ret = DecryptContent(buf, size, psw, pswSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 1073 | WOLFSSL_MSG("Decryption failed, algorithm not compiled in?"); |
wolfSSL | 15:117db924cf7c | 1074 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1075 | } |
wolfSSL | 15:117db924cf7c | 1076 | |
wolfSSL | 15:117db924cf7c | 1077 | data = buf; |
wolfSSL | 15:117db924cf7c | 1078 | idx = 0; |
wolfSSL | 15:117db924cf7c | 1079 | |
wolfSSL | 15:117db924cf7c | 1080 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 1081 | { |
wolfSSL | 15:117db924cf7c | 1082 | byte* p; |
wolfSSL | 15:117db924cf7c | 1083 | for (printf("\tData = "), p = (byte*)buf; |
wolfSSL | 15:117db924cf7c | 1084 | p < (byte*)buf + size; |
wolfSSL | 15:117db924cf7c | 1085 | printf("%02X", *p), p++); |
wolfSSL | 15:117db924cf7c | 1086 | printf("\n"); |
wolfSSL | 15:117db924cf7c | 1087 | } |
wolfSSL | 15:117db924cf7c | 1088 | #endif |
wolfSSL | 15:117db924cf7c | 1089 | } |
wolfSSL | 15:117db924cf7c | 1090 | else { /* type DATA */ |
wolfSSL | 15:117db924cf7c | 1091 | WOLFSSL_MSG("Parsing PKCS12 DATA Content Info Container"); |
wolfSSL | 15:117db924cf7c | 1092 | data = ci->data; |
wolfSSL | 16:8e0d178b1d1e | 1093 | if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 1094 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 16:8e0d178b1d1e | 1095 | } |
wolfSSL | 16:8e0d178b1d1e | 1096 | |
wolfSSL | 16:8e0d178b1d1e | 1097 | if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { |
wolfSSL | 15:117db924cf7c | 1098 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1099 | } |
wolfSSL | 15:117db924cf7c | 1100 | if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { |
wolfSSL | 16:8e0d178b1d1e | 1101 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1102 | } |
wolfSSL | 16:8e0d178b1d1e | 1103 | |
wolfSSL | 16:8e0d178b1d1e | 1104 | if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 1105 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 16:8e0d178b1d1e | 1106 | } |
wolfSSL | 16:8e0d178b1d1e | 1107 | if (tag != ASN_OCTET_STRING) { |
wolfSSL | 15:117db924cf7c | 1108 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1109 | } |
wolfSSL | 15:117db924cf7c | 1110 | if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 1111 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1112 | } |
wolfSSL | 15:117db924cf7c | 1113 | |
wolfSSL | 15:117db924cf7c | 1114 | } |
wolfSSL | 15:117db924cf7c | 1115 | |
wolfSSL | 15:117db924cf7c | 1116 | /* parse through bags in ContentInfo */ |
wolfSSL | 15:117db924cf7c | 1117 | if ((ret = GetSequence(data, &idx, &totalSz, ci->dataSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 1118 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1119 | } |
wolfSSL | 15:117db924cf7c | 1120 | totalSz += idx; |
wolfSSL | 15:117db924cf7c | 1121 | |
wolfSSL | 15:117db924cf7c | 1122 | while ((int)idx < totalSz) { |
wolfSSL | 15:117db924cf7c | 1123 | int bagSz; |
wolfSSL | 15:117db924cf7c | 1124 | if ((ret = GetSequence(data, &idx, &bagSz, ci->dataSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 1125 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1126 | } |
wolfSSL | 15:117db924cf7c | 1127 | bagSz += idx; |
wolfSSL | 15:117db924cf7c | 1128 | |
wolfSSL | 15:117db924cf7c | 1129 | if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType, |
wolfSSL | 15:117db924cf7c | 1130 | ci->dataSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 1131 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1132 | } |
wolfSSL | 15:117db924cf7c | 1133 | |
wolfSSL | 15:117db924cf7c | 1134 | switch (oid) { |
wolfSSL | 15:117db924cf7c | 1135 | case WC_PKCS12_KeyBag: /* 667 */ |
wolfSSL | 15:117db924cf7c | 1136 | WOLFSSL_MSG("PKCS12 Key Bag found"); |
wolfSSL | 16:8e0d178b1d1e | 1137 | if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 1138 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 16:8e0d178b1d1e | 1139 | } |
wolfSSL | 16:8e0d178b1d1e | 1140 | if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { |
wolfSSL | 15:117db924cf7c | 1141 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1142 | } |
wolfSSL | 15:117db924cf7c | 1143 | if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { |
wolfSSL | 16:8e0d178b1d1e | 1144 | if (ret == 0) |
wolfSSL | 16:8e0d178b1d1e | 1145 | ret = ASN_PARSE_E; |
wolfSSL | 15:117db924cf7c | 1146 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1147 | } |
wolfSSL | 15:117db924cf7c | 1148 | if (*pkey == NULL) { |
wolfSSL | 15:117db924cf7c | 1149 | *pkey = (byte*)XMALLOC(size, pkcs12->heap, |
wolfSSL | 15:117db924cf7c | 1150 | DYNAMIC_TYPE_PUBLIC_KEY); |
wolfSSL | 15:117db924cf7c | 1151 | if (*pkey == NULL) { |
wolfSSL | 15:117db924cf7c | 1152 | ERROR_OUT(MEMORY_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1153 | } |
wolfSSL | 15:117db924cf7c | 1154 | XMEMCPY(*pkey, data + idx, size); |
wolfSSL | 16:8e0d178b1d1e | 1155 | *pkeySz = ToTraditional_ex(*pkey, size, &algId); |
wolfSSL | 15:117db924cf7c | 1156 | } |
wolfSSL | 15:117db924cf7c | 1157 | |
wolfSSL | 15:117db924cf7c | 1158 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 1159 | { |
wolfSSL | 15:117db924cf7c | 1160 | byte* p; |
wolfSSL | 15:117db924cf7c | 1161 | for (printf("\tKey = "), p = (byte*)*pkey; |
wolfSSL | 15:117db924cf7c | 1162 | p < (byte*)*pkey + size; |
wolfSSL | 15:117db924cf7c | 1163 | printf("%02X", *p), p++); |
wolfSSL | 15:117db924cf7c | 1164 | printf("\n"); |
wolfSSL | 15:117db924cf7c | 1165 | } |
wolfSSL | 15:117db924cf7c | 1166 | #endif |
wolfSSL | 15:117db924cf7c | 1167 | idx += size; |
wolfSSL | 15:117db924cf7c | 1168 | break; |
wolfSSL | 15:117db924cf7c | 1169 | |
wolfSSL | 15:117db924cf7c | 1170 | case WC_PKCS12_ShroudedKeyBag: /* 668 */ |
wolfSSL | 15:117db924cf7c | 1171 | { |
wolfSSL | 15:117db924cf7c | 1172 | byte* k; |
wolfSSL | 15:117db924cf7c | 1173 | |
wolfSSL | 15:117db924cf7c | 1174 | WOLFSSL_MSG("PKCS12 Shrouded Key Bag found"); |
wolfSSL | 16:8e0d178b1d1e | 1175 | if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 1176 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 16:8e0d178b1d1e | 1177 | } |
wolfSSL | 16:8e0d178b1d1e | 1178 | if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { |
wolfSSL | 15:117db924cf7c | 1179 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1180 | } |
wolfSSL | 15:117db924cf7c | 1181 | if ((ret = GetLength(data, &idx, &size, |
wolfSSL | 15:117db924cf7c | 1182 | ci->dataSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 1183 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1184 | } |
wolfSSL | 15:117db924cf7c | 1185 | |
wolfSSL | 15:117db924cf7c | 1186 | k = (byte*)XMALLOC(size, pkcs12->heap, |
wolfSSL | 15:117db924cf7c | 1187 | DYNAMIC_TYPE_PUBLIC_KEY); |
wolfSSL | 15:117db924cf7c | 1188 | if (k == NULL) { |
wolfSSL | 15:117db924cf7c | 1189 | ERROR_OUT(MEMORY_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1190 | } |
wolfSSL | 15:117db924cf7c | 1191 | XMEMCPY(k, data + idx, size); |
wolfSSL | 15:117db924cf7c | 1192 | |
wolfSSL | 15:117db924cf7c | 1193 | /* overwrites input, be warned */ |
wolfSSL | 16:8e0d178b1d1e | 1194 | if ((ret = ToTraditionalEnc(k, size, psw, pswSz, |
wolfSSL | 16:8e0d178b1d1e | 1195 | &algId)) < 0) { |
wolfSSL | 15:117db924cf7c | 1196 | XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); |
wolfSSL | 15:117db924cf7c | 1197 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1198 | } |
wolfSSL | 15:117db924cf7c | 1199 | |
wolfSSL | 15:117db924cf7c | 1200 | if (ret < size) { |
wolfSSL | 15:117db924cf7c | 1201 | /* shrink key buffer */ |
wolfSSL | 15:117db924cf7c | 1202 | byte* tmp = (byte*)XMALLOC(ret, pkcs12->heap, |
wolfSSL | 15:117db924cf7c | 1203 | DYNAMIC_TYPE_PUBLIC_KEY); |
wolfSSL | 15:117db924cf7c | 1204 | if (tmp == NULL) { |
wolfSSL | 15:117db924cf7c | 1205 | XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); |
wolfSSL | 15:117db924cf7c | 1206 | ERROR_OUT(MEMORY_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1207 | } |
wolfSSL | 15:117db924cf7c | 1208 | XMEMCPY(tmp, k, ret); |
wolfSSL | 15:117db924cf7c | 1209 | XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); |
wolfSSL | 15:117db924cf7c | 1210 | k = tmp; |
wolfSSL | 15:117db924cf7c | 1211 | } |
wolfSSL | 15:117db924cf7c | 1212 | size = ret; |
wolfSSL | 15:117db924cf7c | 1213 | |
wolfSSL | 15:117db924cf7c | 1214 | if (*pkey == NULL) { |
wolfSSL | 15:117db924cf7c | 1215 | *pkey = k; |
wolfSSL | 15:117db924cf7c | 1216 | *pkeySz = size; |
wolfSSL | 15:117db924cf7c | 1217 | } |
wolfSSL | 15:117db924cf7c | 1218 | else { /* only expecting one key */ |
wolfSSL | 15:117db924cf7c | 1219 | XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); |
wolfSSL | 15:117db924cf7c | 1220 | } |
wolfSSL | 15:117db924cf7c | 1221 | idx += size; |
wolfSSL | 15:117db924cf7c | 1222 | |
wolfSSL | 15:117db924cf7c | 1223 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 1224 | { |
wolfSSL | 15:117db924cf7c | 1225 | byte* p; |
wolfSSL | 15:117db924cf7c | 1226 | for (printf("\tKey = "), p = (byte*)k; |
wolfSSL | 15:117db924cf7c | 1227 | p < (byte*)k + ret; |
wolfSSL | 15:117db924cf7c | 1228 | printf("%02X", *p), p++); |
wolfSSL | 15:117db924cf7c | 1229 | printf("\n"); |
wolfSSL | 15:117db924cf7c | 1230 | } |
wolfSSL | 15:117db924cf7c | 1231 | #endif |
wolfSSL | 15:117db924cf7c | 1232 | } |
wolfSSL | 15:117db924cf7c | 1233 | break; |
wolfSSL | 15:117db924cf7c | 1234 | |
wolfSSL | 15:117db924cf7c | 1235 | case WC_PKCS12_CertBag: /* 669 */ |
wolfSSL | 15:117db924cf7c | 1236 | { |
wolfSSL | 15:117db924cf7c | 1237 | WC_DerCertList* node; |
wolfSSL | 15:117db924cf7c | 1238 | WOLFSSL_MSG("PKCS12 Cert Bag found"); |
wolfSSL | 16:8e0d178b1d1e | 1239 | if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 1240 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 16:8e0d178b1d1e | 1241 | } |
wolfSSL | 16:8e0d178b1d1e | 1242 | if (tag != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { |
wolfSSL | 15:117db924cf7c | 1243 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1244 | } |
wolfSSL | 15:117db924cf7c | 1245 | if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 1246 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1247 | } |
wolfSSL | 15:117db924cf7c | 1248 | |
wolfSSL | 15:117db924cf7c | 1249 | /* get cert bag type */ |
wolfSSL | 15:117db924cf7c | 1250 | if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) <0) { |
wolfSSL | 15:117db924cf7c | 1251 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1252 | } |
wolfSSL | 15:117db924cf7c | 1253 | |
wolfSSL | 15:117db924cf7c | 1254 | if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType, |
wolfSSL | 15:117db924cf7c | 1255 | ci->dataSz)) < 0) { |
wolfSSL | 15:117db924cf7c | 1256 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1257 | } |
wolfSSL | 15:117db924cf7c | 1258 | |
wolfSSL | 15:117db924cf7c | 1259 | switch (oid) { |
wolfSSL | 15:117db924cf7c | 1260 | case WC_PKCS12_CertBag_Type1: /* 675 */ |
wolfSSL | 15:117db924cf7c | 1261 | /* type 1 */ |
wolfSSL | 15:117db924cf7c | 1262 | WOLFSSL_MSG("PKCS12 cert bag type 1"); |
wolfSSL | 16:8e0d178b1d1e | 1263 | if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 1264 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 16:8e0d178b1d1e | 1265 | } |
wolfSSL | 16:8e0d178b1d1e | 1266 | if (tag != (ASN_CONSTRUCTED | |
wolfSSL | 16:8e0d178b1d1e | 1267 | ASN_CONTEXT_SPECIFIC)) { |
wolfSSL | 15:117db924cf7c | 1268 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1269 | } |
wolfSSL | 15:117db924cf7c | 1270 | if ((ret = GetLength(data, &idx, &size, ci->dataSz)) |
wolfSSL | 15:117db924cf7c | 1271 | <= 0) { |
wolfSSL | 16:8e0d178b1d1e | 1272 | if (ret == 0) |
wolfSSL | 16:8e0d178b1d1e | 1273 | ret = ASN_PARSE_E; |
wolfSSL | 15:117db924cf7c | 1274 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1275 | } |
wolfSSL | 16:8e0d178b1d1e | 1276 | if (GetASNTag(data, &idx, &tag, ci->dataSz) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 1277 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 16:8e0d178b1d1e | 1278 | } |
wolfSSL | 16:8e0d178b1d1e | 1279 | if (tag != ASN_OCTET_STRING) { |
wolfSSL | 15:117db924cf7c | 1280 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1281 | |
wolfSSL | 15:117db924cf7c | 1282 | } |
wolfSSL | 15:117db924cf7c | 1283 | if ((ret = GetLength(data, &idx, &size, ci->dataSz)) |
wolfSSL | 15:117db924cf7c | 1284 | < 0) { |
wolfSSL | 15:117db924cf7c | 1285 | goto exit_pk12par; |
wolfSSL | 15:117db924cf7c | 1286 | } |
wolfSSL | 15:117db924cf7c | 1287 | break; |
wolfSSL | 15:117db924cf7c | 1288 | default: |
wolfSSL | 15:117db924cf7c | 1289 | WOLFSSL_MSG("Unknown PKCS12 cert bag type"); |
wolfSSL | 15:117db924cf7c | 1290 | } |
wolfSSL | 15:117db924cf7c | 1291 | |
wolfSSL | 15:117db924cf7c | 1292 | if (size + idx > (word32)bagSz) { |
wolfSSL | 15:117db924cf7c | 1293 | ERROR_OUT(ASN_PARSE_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1294 | } |
wolfSSL | 15:117db924cf7c | 1295 | |
wolfSSL | 15:117db924cf7c | 1296 | /* list to hold all certs found */ |
wolfSSL | 15:117db924cf7c | 1297 | node = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), |
wolfSSL | 15:117db924cf7c | 1298 | pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 1299 | if (node == NULL) { |
wolfSSL | 15:117db924cf7c | 1300 | ERROR_OUT(MEMORY_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1301 | } |
wolfSSL | 15:117db924cf7c | 1302 | XMEMSET(node, 0, sizeof(WC_DerCertList)); |
wolfSSL | 15:117db924cf7c | 1303 | |
wolfSSL | 15:117db924cf7c | 1304 | node->buffer = (byte*)XMALLOC(size, pkcs12->heap, |
wolfSSL | 15:117db924cf7c | 1305 | DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 1306 | if (node->buffer == NULL) { |
wolfSSL | 15:117db924cf7c | 1307 | XFREE(node, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 1308 | ERROR_OUT(MEMORY_E, exit_pk12par); |
wolfSSL | 15:117db924cf7c | 1309 | } |
wolfSSL | 15:117db924cf7c | 1310 | XMEMCPY(node->buffer, data + idx, size); |
wolfSSL | 15:117db924cf7c | 1311 | node->bufferSz = size; |
wolfSSL | 15:117db924cf7c | 1312 | |
wolfSSL | 15:117db924cf7c | 1313 | /* put the new node into the list */ |
wolfSSL | 15:117db924cf7c | 1314 | if (certList != NULL) { |
wolfSSL | 15:117db924cf7c | 1315 | WOLFSSL_MSG("Pushing new cert onto queue"); |
wolfSSL | 15:117db924cf7c | 1316 | tailList->next = node; |
wolfSSL | 15:117db924cf7c | 1317 | tailList = node; |
wolfSSL | 15:117db924cf7c | 1318 | } |
wolfSSL | 15:117db924cf7c | 1319 | else { |
wolfSSL | 15:117db924cf7c | 1320 | certList = node; |
wolfSSL | 15:117db924cf7c | 1321 | tailList = node; |
wolfSSL | 15:117db924cf7c | 1322 | } |
wolfSSL | 15:117db924cf7c | 1323 | |
wolfSSL | 15:117db924cf7c | 1324 | /* on to next */ |
wolfSSL | 15:117db924cf7c | 1325 | idx += size; |
wolfSSL | 15:117db924cf7c | 1326 | } |
wolfSSL | 15:117db924cf7c | 1327 | break; |
wolfSSL | 15:117db924cf7c | 1328 | |
wolfSSL | 15:117db924cf7c | 1329 | case WC_PKCS12_CrlBag: /* 670 */ |
wolfSSL | 15:117db924cf7c | 1330 | WOLFSSL_MSG("PKCS12 CRL BAG not yet supported"); |
wolfSSL | 15:117db924cf7c | 1331 | break; |
wolfSSL | 15:117db924cf7c | 1332 | |
wolfSSL | 15:117db924cf7c | 1333 | case WC_PKCS12_SecretBag: /* 671 */ |
wolfSSL | 15:117db924cf7c | 1334 | WOLFSSL_MSG("PKCS12 Secret BAG not yet supported"); |
wolfSSL | 15:117db924cf7c | 1335 | break; |
wolfSSL | 15:117db924cf7c | 1336 | |
wolfSSL | 15:117db924cf7c | 1337 | case WC_PKCS12_SafeContentsBag: /* 672 */ |
wolfSSL | 15:117db924cf7c | 1338 | WOLFSSL_MSG("PKCS12 Safe Contents BAG not yet supported"); |
wolfSSL | 15:117db924cf7c | 1339 | break; |
wolfSSL | 15:117db924cf7c | 1340 | |
wolfSSL | 15:117db924cf7c | 1341 | default: |
wolfSSL | 15:117db924cf7c | 1342 | WOLFSSL_MSG("Unknown PKCS12 BAG type found"); |
wolfSSL | 15:117db924cf7c | 1343 | } |
wolfSSL | 15:117db924cf7c | 1344 | |
wolfSSL | 15:117db924cf7c | 1345 | /* Attribute, unknown bag or unsupported */ |
wolfSSL | 15:117db924cf7c | 1346 | if ((int)idx < bagSz) { |
wolfSSL | 15:117db924cf7c | 1347 | idx = bagSz; /* skip for now */ |
wolfSSL | 15:117db924cf7c | 1348 | } |
wolfSSL | 15:117db924cf7c | 1349 | } |
wolfSSL | 15:117db924cf7c | 1350 | |
wolfSSL | 15:117db924cf7c | 1351 | /* free temporary buffer */ |
wolfSSL | 15:117db924cf7c | 1352 | if (buf != NULL) { |
wolfSSL | 15:117db924cf7c | 1353 | XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 1354 | buf = NULL; |
wolfSSL | 15:117db924cf7c | 1355 | } |
wolfSSL | 15:117db924cf7c | 1356 | |
wolfSSL | 15:117db924cf7c | 1357 | ci = ci->next; |
wolfSSL | 15:117db924cf7c | 1358 | WOLFSSL_MSG("Done Parsing PKCS12 Content Info Container"); |
wolfSSL | 15:117db924cf7c | 1359 | } |
wolfSSL | 15:117db924cf7c | 1360 | |
wolfSSL | 15:117db924cf7c | 1361 | /* check if key pair, remove from list */ |
wolfSSL | 15:117db924cf7c | 1362 | if (*pkey != NULL) { |
wolfSSL | 15:117db924cf7c | 1363 | freeDecCertList(&certList, pkey, pkeySz, cert, certSz, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 1364 | } |
wolfSSL | 15:117db924cf7c | 1365 | |
wolfSSL | 15:117db924cf7c | 1366 | /* if ca arg provided return certList, otherwise free it */ |
wolfSSL | 15:117db924cf7c | 1367 | if (ca != NULL) { |
wolfSSL | 15:117db924cf7c | 1368 | *ca = certList; |
wolfSSL | 15:117db924cf7c | 1369 | } |
wolfSSL | 15:117db924cf7c | 1370 | else { |
wolfSSL | 15:117db924cf7c | 1371 | /* free list, not wanted */ |
wolfSSL | 15:117db924cf7c | 1372 | wc_FreeCertList(certList, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 1373 | } |
wolfSSL | 16:8e0d178b1d1e | 1374 | (void)tailList; /* not used */ |
wolfSSL | 15:117db924cf7c | 1375 | |
wolfSSL | 15:117db924cf7c | 1376 | ret = 0; /* success */ |
wolfSSL | 15:117db924cf7c | 1377 | |
wolfSSL | 15:117db924cf7c | 1378 | exit_pk12par: |
wolfSSL | 15:117db924cf7c | 1379 | |
wolfSSL | 15:117db924cf7c | 1380 | if (ret != 0) { |
wolfSSL | 15:117db924cf7c | 1381 | /* failure cleanup */ |
wolfSSL | 15:117db924cf7c | 1382 | if (*pkey) { |
wolfSSL | 15:117db924cf7c | 1383 | XFREE(*pkey, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); |
wolfSSL | 15:117db924cf7c | 1384 | *pkey = NULL; |
wolfSSL | 15:117db924cf7c | 1385 | } |
wolfSSL | 15:117db924cf7c | 1386 | if (buf) { |
wolfSSL | 15:117db924cf7c | 1387 | XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 1388 | buf = NULL; |
wolfSSL | 15:117db924cf7c | 1389 | } |
wolfSSL | 15:117db924cf7c | 1390 | |
wolfSSL | 15:117db924cf7c | 1391 | wc_FreeCertList(certList, pkcs12->heap); |
wolfSSL | 15:117db924cf7c | 1392 | } |
wolfSSL | 15:117db924cf7c | 1393 | |
wolfSSL | 15:117db924cf7c | 1394 | return ret; |
wolfSSL | 15:117db924cf7c | 1395 | } |
wolfSSL | 15:117db924cf7c | 1396 | |
wolfSSL | 15:117db924cf7c | 1397 | |
wolfSSL | 15:117db924cf7c | 1398 | /* Helper function to shroud keys. |
wolfSSL | 15:117db924cf7c | 1399 | * |
wolfSSL | 15:117db924cf7c | 1400 | * pkcs12 structure to use with shrouding key |
wolfSSL | 15:117db924cf7c | 1401 | * rng random number generator used |
wolfSSL | 15:117db924cf7c | 1402 | * out buffer to hold results |
wolfSSL | 15:117db924cf7c | 1403 | * outSz size of out buffer |
wolfSSL | 15:117db924cf7c | 1404 | * key key that is going to be shrouded |
wolfSSL | 15:117db924cf7c | 1405 | * keySz size of key buffer |
wolfSSL | 15:117db924cf7c | 1406 | * vAlgo algorithm version |
wolfSSL | 15:117db924cf7c | 1407 | * pass password to use |
wolfSSL | 15:117db924cf7c | 1408 | * passSz size of pass buffer |
wolfSSL | 15:117db924cf7c | 1409 | * itt number of iterations |
wolfSSL | 15:117db924cf7c | 1410 | * |
wolfSSL | 15:117db924cf7c | 1411 | * returns the size of the shrouded key on success |
wolfSSL | 15:117db924cf7c | 1412 | */ |
wolfSSL | 15:117db924cf7c | 1413 | static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng, |
wolfSSL | 15:117db924cf7c | 1414 | byte* out, word32* outSz, byte* key, word32 keySz, int vAlgo, |
wolfSSL | 15:117db924cf7c | 1415 | const char* pass, int passSz, int itt) |
wolfSSL | 15:117db924cf7c | 1416 | { |
wolfSSL | 15:117db924cf7c | 1417 | void* heap; |
wolfSSL | 15:117db924cf7c | 1418 | word32 tmpIdx = 0; |
wolfSSL | 15:117db924cf7c | 1419 | int vPKCS = 1; /* PKCS#12 default set to 1 */ |
wolfSSL | 15:117db924cf7c | 1420 | word32 sz; |
wolfSSL | 15:117db924cf7c | 1421 | word32 totalSz = 0; |
wolfSSL | 15:117db924cf7c | 1422 | int ret; |
wolfSSL | 15:117db924cf7c | 1423 | |
wolfSSL | 15:117db924cf7c | 1424 | |
wolfSSL | 15:117db924cf7c | 1425 | if (outSz == NULL || pkcs12 == NULL || rng == NULL || key == NULL || |
wolfSSL | 15:117db924cf7c | 1426 | pass == NULL) { |
wolfSSL | 15:117db924cf7c | 1427 | return BAD_FUNC_ARG; |
wolfSSL | 15:117db924cf7c | 1428 | } |
wolfSSL | 15:117db924cf7c | 1429 | |
wolfSSL | 15:117db924cf7c | 1430 | heap = wc_PKCS12_GetHeap(pkcs12); |
wolfSSL | 15:117db924cf7c | 1431 | |
wolfSSL | 15:117db924cf7c | 1432 | /* check if trying to get size */ |
wolfSSL | 15:117db924cf7c | 1433 | if (out != NULL) { |
wolfSSL | 15:117db924cf7c | 1434 | tmpIdx += MAX_LENGTH_SZ + 1; /* save room for length and tag (+1) */ |
wolfSSL | 15:117db924cf7c | 1435 | sz = *outSz - tmpIdx; |
wolfSSL | 15:117db924cf7c | 1436 | } |
wolfSSL | 15:117db924cf7c | 1437 | |
wolfSSL | 15:117db924cf7c | 1438 | /* case of no encryption */ |
wolfSSL | 15:117db924cf7c | 1439 | if (vAlgo < 0) { |
wolfSSL | 15:117db924cf7c | 1440 | const byte* curveOID = NULL; |
wolfSSL | 15:117db924cf7c | 1441 | word32 oidSz = 0; |
wolfSSL | 15:117db924cf7c | 1442 | int algoID; |
wolfSSL | 15:117db924cf7c | 1443 | |
wolfSSL | 15:117db924cf7c | 1444 | WOLFSSL_MSG("creating PKCS12 Key Bag"); |
wolfSSL | 15:117db924cf7c | 1445 | |
wolfSSL | 15:117db924cf7c | 1446 | /* check key type and get OID if ECC */ |
wolfSSL | 15:117db924cf7c | 1447 | if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap)) |
wolfSSL | 15:117db924cf7c | 1448 | < 0) { |
wolfSSL | 15:117db924cf7c | 1449 | return ret; |
wolfSSL | 15:117db924cf7c | 1450 | } |
wolfSSL | 15:117db924cf7c | 1451 | |
wolfSSL | 15:117db924cf7c | 1452 | /* PKCS#8 wrapping around key */ |
wolfSSL | 15:117db924cf7c | 1453 | ret = wc_CreatePKCS8Key(out + tmpIdx, &sz, key, keySz, algoID, |
wolfSSL | 15:117db924cf7c | 1454 | curveOID, oidSz); |
wolfSSL | 15:117db924cf7c | 1455 | } |
wolfSSL | 15:117db924cf7c | 1456 | else { |
wolfSSL | 15:117db924cf7c | 1457 | WOLFSSL_MSG("creating PKCS12 Shrouded Key Bag"); |
wolfSSL | 15:117db924cf7c | 1458 | |
wolfSSL | 15:117db924cf7c | 1459 | if (vAlgo == PBE_SHA1_DES) { |
wolfSSL | 15:117db924cf7c | 1460 | vPKCS = PKCS5; |
wolfSSL | 15:117db924cf7c | 1461 | vAlgo = 10; |
wolfSSL | 15:117db924cf7c | 1462 | } |
wolfSSL | 15:117db924cf7c | 1463 | |
wolfSSL | 15:117db924cf7c | 1464 | ret = UnTraditionalEnc(key, keySz, out + tmpIdx, &sz, pass, passSz, |
wolfSSL | 15:117db924cf7c | 1465 | vPKCS, vAlgo, NULL, 0, itt, rng, heap); |
wolfSSL | 15:117db924cf7c | 1466 | } |
wolfSSL | 15:117db924cf7c | 1467 | if (ret == LENGTH_ONLY_E) { |
wolfSSL | 15:117db924cf7c | 1468 | *outSz = sz + MAX_LENGTH_SZ + 1; |
wolfSSL | 15:117db924cf7c | 1469 | return LENGTH_ONLY_E; |
wolfSSL | 15:117db924cf7c | 1470 | } |
wolfSSL | 15:117db924cf7c | 1471 | if (ret < 0) { |
wolfSSL | 15:117db924cf7c | 1472 | return ret; |
wolfSSL | 15:117db924cf7c | 1473 | } |
wolfSSL | 15:117db924cf7c | 1474 | |
wolfSSL | 15:117db924cf7c | 1475 | totalSz += ret; |
wolfSSL | 15:117db924cf7c | 1476 | |
wolfSSL | 15:117db924cf7c | 1477 | /* out should not be null at this point but check before writing */ |
wolfSSL | 15:117db924cf7c | 1478 | if (out == NULL) { |
wolfSSL | 15:117db924cf7c | 1479 | return BAD_FUNC_ARG; |
wolfSSL | 15:117db924cf7c | 1480 | } |
wolfSSL | 15:117db924cf7c | 1481 | |
wolfSSL | 15:117db924cf7c | 1482 | /* rewind index and set tag and length */ |
wolfSSL | 15:117db924cf7c | 1483 | tmpIdx -= MAX_LENGTH_SZ + 1; |
wolfSSL | 15:117db924cf7c | 1484 | sz = SetExplicit(0, ret, out + tmpIdx); |
wolfSSL | 15:117db924cf7c | 1485 | tmpIdx += sz; totalSz += sz; |
wolfSSL | 15:117db924cf7c | 1486 | XMEMMOVE(out + tmpIdx, out + MAX_LENGTH_SZ + 1, ret); |
wolfSSL | 15:117db924cf7c | 1487 | |
wolfSSL | 15:117db924cf7c | 1488 | return totalSz; |
wolfSSL | 15:117db924cf7c | 1489 | } |
wolfSSL | 15:117db924cf7c | 1490 | |
wolfSSL | 15:117db924cf7c | 1491 | |
wolfSSL | 15:117db924cf7c | 1492 | /* Helper function to create key bag. |
wolfSSL | 15:117db924cf7c | 1493 | * |
wolfSSL | 15:117db924cf7c | 1494 | * pkcs12 structure to use with key bag |
wolfSSL | 15:117db924cf7c | 1495 | * rng random number generator used |
wolfSSL | 15:117db924cf7c | 1496 | * out buffer to hold results |
wolfSSL | 15:117db924cf7c | 1497 | * outSz size of out buffer |
wolfSSL | 15:117db924cf7c | 1498 | * key key that is going into key bag |
wolfSSL | 15:117db924cf7c | 1499 | * keySz size of key buffer |
wolfSSL | 15:117db924cf7c | 1500 | * algo algorithm version |
wolfSSL | 15:117db924cf7c | 1501 | * iter number of iterations |
wolfSSL | 15:117db924cf7c | 1502 | * pass password to use |
wolfSSL | 15:117db924cf7c | 1503 | * passSz size of pass buffer |
wolfSSL | 15:117db924cf7c | 1504 | * |
wolfSSL | 15:117db924cf7c | 1505 | * returns the size of the key bag on success |
wolfSSL | 15:117db924cf7c | 1506 | */ |
wolfSSL | 15:117db924cf7c | 1507 | static int wc_PKCS12_create_key_bag(WC_PKCS12* pkcs12, WC_RNG* rng, |
wolfSSL | 15:117db924cf7c | 1508 | byte* out, word32* outSz, byte* key, word32 keySz, int algo, int iter, |
wolfSSL | 15:117db924cf7c | 1509 | char* pass, int passSz) |
wolfSSL | 15:117db924cf7c | 1510 | { |
wolfSSL | 15:117db924cf7c | 1511 | void* heap; |
wolfSSL | 15:117db924cf7c | 1512 | byte* tmp; |
wolfSSL | 15:117db924cf7c | 1513 | word32 length = 0; |
wolfSSL | 15:117db924cf7c | 1514 | word32 idx = 0; |
wolfSSL | 15:117db924cf7c | 1515 | word32 totalSz = 0; |
wolfSSL | 15:117db924cf7c | 1516 | word32 sz; |
wolfSSL | 15:117db924cf7c | 1517 | word32 i; |
wolfSSL | 15:117db924cf7c | 1518 | word32 tmpSz; |
wolfSSL | 15:117db924cf7c | 1519 | int ret; |
wolfSSL | 15:117db924cf7c | 1520 | |
wolfSSL | 15:117db924cf7c | 1521 | /* get max size for shrouded key */ |
wolfSSL | 15:117db924cf7c | 1522 | ret = wc_PKCS12_shroud_key(pkcs12, rng, NULL, &length, key, keySz, |
wolfSSL | 15:117db924cf7c | 1523 | algo, pass, passSz, iter); |
wolfSSL | 15:117db924cf7c | 1524 | if (ret != LENGTH_ONLY_E && ret < 0) { |
wolfSSL | 15:117db924cf7c | 1525 | return ret; |
wolfSSL | 15:117db924cf7c | 1526 | } |
wolfSSL | 15:117db924cf7c | 1527 | |
wolfSSL | 15:117db924cf7c | 1528 | if (out == NULL) { |
wolfSSL | 15:117db924cf7c | 1529 | *outSz = MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ + 1 + MAX_LENGTH_SZ + |
wolfSSL | 15:117db924cf7c | 1530 | length; |
wolfSSL | 15:117db924cf7c | 1531 | return LENGTH_ONLY_E; |
wolfSSL | 15:117db924cf7c | 1532 | } |
wolfSSL | 15:117db924cf7c | 1533 | |
wolfSSL | 15:117db924cf7c | 1534 | heap = wc_PKCS12_GetHeap(pkcs12); |
wolfSSL | 15:117db924cf7c | 1535 | |
wolfSSL | 15:117db924cf7c | 1536 | /* leave room for sequence */ |
wolfSSL | 15:117db924cf7c | 1537 | idx += MAX_SEQ_SZ; |
wolfSSL | 15:117db924cf7c | 1538 | |
wolfSSL | 15:117db924cf7c | 1539 | if (algo < 0) { /* not encrypted */ |
wolfSSL | 15:117db924cf7c | 1540 | out[idx++] = ASN_OBJECT_ID; totalSz++; |
wolfSSL | 15:117db924cf7c | 1541 | sz = SetLength(sizeof(WC_PKCS12_KeyBag_OID), out + idx); |
wolfSSL | 15:117db924cf7c | 1542 | idx += sz; totalSz += sz; |
wolfSSL | 15:117db924cf7c | 1543 | for (i = 0; i < sizeof(WC_PKCS12_KeyBag_OID); i++) { |
wolfSSL | 15:117db924cf7c | 1544 | out[idx++] = WC_PKCS12_KeyBag_OID[i]; totalSz++; |
wolfSSL | 15:117db924cf7c | 1545 | } |
wolfSSL | 15:117db924cf7c | 1546 | } |
wolfSSL | 15:117db924cf7c | 1547 | else { /* encrypted */ |
wolfSSL | 15:117db924cf7c | 1548 | out[idx++] = ASN_OBJECT_ID; totalSz++; |
wolfSSL | 15:117db924cf7c | 1549 | sz = SetLength(sizeof(WC_PKCS12_ShroudedKeyBag_OID), out + idx); |
wolfSSL | 15:117db924cf7c | 1550 | idx += sz; totalSz += sz; |
wolfSSL | 15:117db924cf7c | 1551 | for (i = 0; i < sizeof(WC_PKCS12_ShroudedKeyBag_OID); i++) { |
wolfSSL | 15:117db924cf7c | 1552 | out[idx++] = WC_PKCS12_ShroudedKeyBag_OID[i]; totalSz++; |
wolfSSL | 15:117db924cf7c | 1553 | } |
wolfSSL | 15:117db924cf7c | 1554 | } |
wolfSSL | 15:117db924cf7c | 1555 | |
wolfSSL | 15:117db924cf7c | 1556 | /* shroud key */ |
wolfSSL | 15:117db924cf7c | 1557 | tmp = (byte*)XMALLOC(length, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 15:117db924cf7c | 1558 | if (tmp == NULL) { |
wolfSSL | 15:117db924cf7c | 1559 | return MEMORY_E; |
wolfSSL | 15:117db924cf7c | 1560 | } |
wolfSSL | 15:117db924cf7c | 1561 | |
wolfSSL | 15:117db924cf7c | 1562 | ret = wc_PKCS12_shroud_key(pkcs12, rng, tmp, &length, key, keySz, |
wolfSSL | 15:117db924cf7c | 1563 | algo, pass, passSz, iter); |
wolfSSL | 15:117db924cf7c | 1564 | if (ret < 0) { |
wolfSSL | 15:117db924cf7c | 1565 | XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 15:117db924cf7c | 1566 | return ret; |
wolfSSL | 15:117db924cf7c | 1567 | } |
wolfSSL | 15:117db924cf7c | 1568 | length = ret; |
wolfSSL | 15:117db924cf7c | 1569 | XMEMCPY(out + idx, tmp, length); |
wolfSSL | 15:117db924cf7c | 1570 | XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 15:117db924cf7c | 1571 | totalSz += length; |
wolfSSL | 15:117db924cf7c | 1572 | |
wolfSSL | 16:8e0d178b1d1e | 1573 | /* set beginning sequence */ |
wolfSSL | 15:117db924cf7c | 1574 | tmpSz = SetSequence(totalSz, out); |
wolfSSL | 15:117db924cf7c | 1575 | XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz); |
wolfSSL | 15:117db924cf7c | 1576 | |
wolfSSL | 15:117db924cf7c | 1577 | (void)heap; |
wolfSSL | 15:117db924cf7c | 1578 | return totalSz + tmpSz; |
wolfSSL | 15:117db924cf7c | 1579 | } |
wolfSSL | 15:117db924cf7c | 1580 | |
wolfSSL | 15:117db924cf7c | 1581 | |
wolfSSL | 15:117db924cf7c | 1582 | /* Helper function to create cert bag. |
wolfSSL | 15:117db924cf7c | 1583 | * |
wolfSSL | 15:117db924cf7c | 1584 | * pkcs12 structure to use with cert bag |
wolfSSL | 15:117db924cf7c | 1585 | * out buffer to hold results |
wolfSSL | 15:117db924cf7c | 1586 | * outSz size of out buffer |
wolfSSL | 15:117db924cf7c | 1587 | * cert cert that is going into cert bag |
wolfSSL | 15:117db924cf7c | 1588 | * certSz size of cert buffer |
wolfSSL | 15:117db924cf7c | 1589 | * |
wolfSSL | 15:117db924cf7c | 1590 | * returns the size of the cert bag on success |
wolfSSL | 15:117db924cf7c | 1591 | */ |
wolfSSL | 15:117db924cf7c | 1592 | static int wc_PKCS12_create_cert_bag(WC_PKCS12* pkcs12, |
wolfSSL | 15:117db924cf7c | 1593 | byte* out, word32* outSz, byte* cert, word32 certSz) |
wolfSSL | 15:117db924cf7c | 1594 | { |
wolfSSL | 15:117db924cf7c | 1595 | word32 length = 0; |
wolfSSL | 15:117db924cf7c | 1596 | word32 idx = 0; |
wolfSSL | 15:117db924cf7c | 1597 | word32 totalSz = 0; |
wolfSSL | 15:117db924cf7c | 1598 | word32 sz; |
wolfSSL | 15:117db924cf7c | 1599 | int WC_CERTBAG_OBJECT_ID = 13; |
wolfSSL | 15:117db924cf7c | 1600 | int WC_CERTBAG1_OBJECT_ID = 12; |
wolfSSL | 15:117db924cf7c | 1601 | word32 i; |
wolfSSL | 15:117db924cf7c | 1602 | word32 tmpSz; |
wolfSSL | 15:117db924cf7c | 1603 | |
wolfSSL | 15:117db924cf7c | 1604 | if (out == NULL) { |
wolfSSL | 15:117db924cf7c | 1605 | *outSz = MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ + |
wolfSSL | 15:117db924cf7c | 1606 | MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 + |
wolfSSL | 15:117db924cf7c | 1607 | MAX_LENGTH_SZ + certSz; |
wolfSSL | 15:117db924cf7c | 1608 | return LENGTH_ONLY_E; |
wolfSSL | 15:117db924cf7c | 1609 | } |
wolfSSL | 15:117db924cf7c | 1610 | |
wolfSSL | 15:117db924cf7c | 1611 | /* check buffer size able to handle max size */ |
wolfSSL | 15:117db924cf7c | 1612 | if (*outSz < (MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ + |
wolfSSL | 15:117db924cf7c | 1613 | MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 + |
wolfSSL | 15:117db924cf7c | 1614 | MAX_LENGTH_SZ + certSz)) { |
wolfSSL | 15:117db924cf7c | 1615 | return BUFFER_E; |
wolfSSL | 15:117db924cf7c | 1616 | } |
wolfSSL | 15:117db924cf7c | 1617 | |
wolfSSL | 15:117db924cf7c | 1618 | /* save room for sequence */ |
wolfSSL | 15:117db924cf7c | 1619 | idx += MAX_SEQ_SZ; |
wolfSSL | 15:117db924cf7c | 1620 | |
wolfSSL | 15:117db924cf7c | 1621 | /* objectId WC_PKCS12_CertBag */ |
wolfSSL | 15:117db924cf7c | 1622 | out[idx++] = ASN_OBJECT_ID; totalSz++; |
wolfSSL | 15:117db924cf7c | 1623 | sz = SetLength(sizeof(WC_PKCS12_CertBag_OID), out + idx); |
wolfSSL | 15:117db924cf7c | 1624 | idx += sz; totalSz += sz; |
wolfSSL | 15:117db924cf7c | 1625 | for (i = 0; i < sizeof(WC_PKCS12_CertBag_OID); i++) { |
wolfSSL | 15:117db924cf7c | 1626 | out[idx++] = WC_PKCS12_CertBag_OID[i]; totalSz++; |
wolfSSL | 15:117db924cf7c | 1627 | } |
wolfSSL | 15:117db924cf7c | 1628 | |
wolfSSL | 15:117db924cf7c | 1629 | /**** Cert Bag type 1 ****/ |
wolfSSL | 15:117db924cf7c | 1630 | out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); totalSz++; |
wolfSSL | 15:117db924cf7c | 1631 | |
wolfSSL | 15:117db924cf7c | 1632 | /* save room for length and sequence */ |
wolfSSL | 15:117db924cf7c | 1633 | idx += MAX_LENGTH_SZ; |
wolfSSL | 15:117db924cf7c | 1634 | idx += MAX_SEQ_SZ; |
wolfSSL | 15:117db924cf7c | 1635 | |
wolfSSL | 15:117db924cf7c | 1636 | /* object id WC_PKCS12_CertBag_Type1 */ |
wolfSSL | 15:117db924cf7c | 1637 | out[idx++] = ASN_OBJECT_ID; length++; |
wolfSSL | 15:117db924cf7c | 1638 | sz = SetLength(sizeof(WC_PKCS12_CertBag_Type1_OID), out + idx); |
wolfSSL | 15:117db924cf7c | 1639 | idx += sz; length += sz; |
wolfSSL | 15:117db924cf7c | 1640 | for (i = 0; i < sizeof(WC_PKCS12_CertBag_Type1_OID); i++) { |
wolfSSL | 15:117db924cf7c | 1641 | out[idx++] = WC_PKCS12_CertBag_Type1_OID[i]; length++; |
wolfSSL | 15:117db924cf7c | 1642 | } |
wolfSSL | 15:117db924cf7c | 1643 | |
wolfSSL | 15:117db924cf7c | 1644 | out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); length++; |
wolfSSL | 15:117db924cf7c | 1645 | sz = 0; |
wolfSSL | 15:117db924cf7c | 1646 | idx += MAX_LENGTH_SZ; /* save room for length */ |
wolfSSL | 15:117db924cf7c | 1647 | |
wolfSSL | 15:117db924cf7c | 1648 | /* place the cert in the buffer */ |
wolfSSL | 15:117db924cf7c | 1649 | out[idx++] = ASN_OCTET_STRING; sz++; |
wolfSSL | 15:117db924cf7c | 1650 | tmpSz = SetLength(certSz, out + idx); |
wolfSSL | 15:117db924cf7c | 1651 | idx += tmpSz; sz += tmpSz; |
wolfSSL | 15:117db924cf7c | 1652 | XMEMCPY(out + idx, cert, certSz); |
wolfSSL | 15:117db924cf7c | 1653 | idx += certSz; sz += certSz; |
wolfSSL | 15:117db924cf7c | 1654 | |
wolfSSL | 15:117db924cf7c | 1655 | /* rewind idx and place length */ |
wolfSSL | 15:117db924cf7c | 1656 | idx -= (sz + MAX_LENGTH_SZ); |
wolfSSL | 15:117db924cf7c | 1657 | tmpSz = SetLength(sz, out + idx); |
wolfSSL | 15:117db924cf7c | 1658 | XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, sz); |
wolfSSL | 15:117db924cf7c | 1659 | idx += tmpSz + sz; length += tmpSz + sz; |
wolfSSL | 15:117db924cf7c | 1660 | |
wolfSSL | 15:117db924cf7c | 1661 | /* rewind idx and set sequence */ |
wolfSSL | 15:117db924cf7c | 1662 | idx -= (length + MAX_SEQ_SZ); |
wolfSSL | 15:117db924cf7c | 1663 | tmpSz = SetSequence(length, out + idx); |
wolfSSL | 15:117db924cf7c | 1664 | XMEMMOVE(out + idx + tmpSz, out + idx + MAX_SEQ_SZ, length); |
wolfSSL | 15:117db924cf7c | 1665 | length += tmpSz; |
wolfSSL | 15:117db924cf7c | 1666 | |
wolfSSL | 15:117db924cf7c | 1667 | /* place final length */ |
wolfSSL | 15:117db924cf7c | 1668 | idx -= MAX_LENGTH_SZ; |
wolfSSL | 15:117db924cf7c | 1669 | tmpSz = SetLength(length, out + idx); |
wolfSSL | 15:117db924cf7c | 1670 | XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length); |
wolfSSL | 15:117db924cf7c | 1671 | length += tmpSz; |
wolfSSL | 15:117db924cf7c | 1672 | |
wolfSSL | 15:117db924cf7c | 1673 | /* place final sequence */ |
wolfSSL | 15:117db924cf7c | 1674 | totalSz += length; |
wolfSSL | 15:117db924cf7c | 1675 | tmpSz = SetSequence(totalSz, out); |
wolfSSL | 15:117db924cf7c | 1676 | XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz); |
wolfSSL | 15:117db924cf7c | 1677 | |
wolfSSL | 15:117db924cf7c | 1678 | (void)pkcs12; |
wolfSSL | 15:117db924cf7c | 1679 | |
wolfSSL | 15:117db924cf7c | 1680 | return totalSz + tmpSz; |
wolfSSL | 15:117db924cf7c | 1681 | } |
wolfSSL | 15:117db924cf7c | 1682 | |
wolfSSL | 15:117db924cf7c | 1683 | |
wolfSSL | 15:117db924cf7c | 1684 | /* Helper function to encrypt content. |
wolfSSL | 15:117db924cf7c | 1685 | * |
wolfSSL | 15:117db924cf7c | 1686 | * pkcs12 structure to use with key bag |
wolfSSL | 15:117db924cf7c | 1687 | * rng random number generator used |
wolfSSL | 15:117db924cf7c | 1688 | * out buffer to hold results |
wolfSSL | 15:117db924cf7c | 1689 | * outSz size of out buffer |
wolfSSL | 15:117db924cf7c | 1690 | * content content to encrypt |
wolfSSL | 15:117db924cf7c | 1691 | * contentSz size of content buffer |
wolfSSL | 15:117db924cf7c | 1692 | * vAlgo algorithm version |
wolfSSL | 15:117db924cf7c | 1693 | * pass password to use |
wolfSSL | 15:117db924cf7c | 1694 | * passSz size of pass buffer |
wolfSSL | 15:117db924cf7c | 1695 | * iter number of iterations |
wolfSSL | 15:117db924cf7c | 1696 | * type content type i.e WC_PKCS12_ENCRYPTED_DATA or WC_PKCS12_DATA |
wolfSSL | 15:117db924cf7c | 1697 | * |
wolfSSL | 15:117db924cf7c | 1698 | * returns the size of result on success |
wolfSSL | 15:117db924cf7c | 1699 | */ |
wolfSSL | 15:117db924cf7c | 1700 | static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, |
wolfSSL | 15:117db924cf7c | 1701 | byte* out, word32* outSz, byte* content, word32 contentSz, int vAlgo, |
wolfSSL | 15:117db924cf7c | 1702 | const char* pass, int passSz, int iter, int type) |
wolfSSL | 15:117db924cf7c | 1703 | { |
wolfSSL | 15:117db924cf7c | 1704 | void* heap; |
wolfSSL | 15:117db924cf7c | 1705 | int vPKCS = 1; /* PKCS#12 is always set to 1 */ |
wolfSSL | 15:117db924cf7c | 1706 | int ret; |
wolfSSL | 15:117db924cf7c | 1707 | byte* tmp; |
wolfSSL | 15:117db924cf7c | 1708 | word32 idx = 0; |
wolfSSL | 15:117db924cf7c | 1709 | word32 totalSz = 0; |
wolfSSL | 15:117db924cf7c | 1710 | word32 length = 0; |
wolfSSL | 15:117db924cf7c | 1711 | word32 tmpSz; |
wolfSSL | 15:117db924cf7c | 1712 | word32 encSz; |
wolfSSL | 16:8e0d178b1d1e | 1713 | |
wolfSSL | 16:8e0d178b1d1e | 1714 | byte seq[MAX_SEQ_SZ]; |
wolfSSL | 15:117db924cf7c | 1715 | |
wolfSSL | 15:117db924cf7c | 1716 | WOLFSSL_MSG("encrypting PKCS12 content"); |
wolfSSL | 15:117db924cf7c | 1717 | |
wolfSSL | 15:117db924cf7c | 1718 | heap = wc_PKCS12_GetHeap(pkcs12); |
wolfSSL | 15:117db924cf7c | 1719 | |
wolfSSL | 15:117db924cf7c | 1720 | /* ENCRYPTED DATA |
wolfSSL | 15:117db924cf7c | 1721 | * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC |
wolfSSL | 15:117db924cf7c | 1722 | * length |
wolfSSL | 15:117db924cf7c | 1723 | * sequence |
wolfSSL | 15:117db924cf7c | 1724 | * short int |
wolfSSL | 15:117db924cf7c | 1725 | * sequence |
wolfSSL | 15:117db924cf7c | 1726 | * get object id */ |
wolfSSL | 15:117db924cf7c | 1727 | if (type == WC_PKCS12_ENCRYPTED_DATA) { |
wolfSSL | 16:8e0d178b1d1e | 1728 | word32 outerSz = 0; |
wolfSSL | 15:117db924cf7c | 1729 | |
wolfSSL | 15:117db924cf7c | 1730 | encSz = contentSz; |
wolfSSL | 15:117db924cf7c | 1731 | if ((ret = EncryptContent(NULL, contentSz, NULL, &encSz, |
wolfSSL | 15:117db924cf7c | 1732 | pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) { |
wolfSSL | 15:117db924cf7c | 1733 | if (ret != LENGTH_ONLY_E) { |
wolfSSL | 15:117db924cf7c | 1734 | return ret; |
wolfSSL | 15:117db924cf7c | 1735 | } |
wolfSSL | 15:117db924cf7c | 1736 | } |
wolfSSL | 15:117db924cf7c | 1737 | |
wolfSSL | 16:8e0d178b1d1e | 1738 | /* calculate size */ |
wolfSSL | 16:8e0d178b1d1e | 1739 | totalSz = SetObjectId(sizeof(WC_PKCS12_ENCRYPTED_OID), seq); |
wolfSSL | 16:8e0d178b1d1e | 1740 | totalSz += sizeof(WC_PKCS12_ENCRYPTED_OID); |
wolfSSL | 16:8e0d178b1d1e | 1741 | totalSz += ASN_TAG_SZ; |
wolfSSL | 16:8e0d178b1d1e | 1742 | |
wolfSSL | 16:8e0d178b1d1e | 1743 | length = SetMyVersion(0, seq, 0); |
wolfSSL | 16:8e0d178b1d1e | 1744 | tmpSz = SetObjectId(sizeof(WC_PKCS12_DATA_OID), seq); |
wolfSSL | 16:8e0d178b1d1e | 1745 | tmpSz += sizeof(WC_PKCS12_DATA_OID); |
wolfSSL | 16:8e0d178b1d1e | 1746 | tmpSz += encSz; |
wolfSSL | 16:8e0d178b1d1e | 1747 | length += SetSequence(tmpSz, seq) + tmpSz; |
wolfSSL | 16:8e0d178b1d1e | 1748 | outerSz = SetSequence(length, seq) + length; |
wolfSSL | 16:8e0d178b1d1e | 1749 | |
wolfSSL | 16:8e0d178b1d1e | 1750 | totalSz += SetLength(outerSz, seq) + outerSz; |
wolfSSL | 16:8e0d178b1d1e | 1751 | if (out == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 1752 | *outSz = totalSz + SetSequence(totalSz, seq); |
wolfSSL | 16:8e0d178b1d1e | 1753 | return LENGTH_ONLY_E; |
wolfSSL | 16:8e0d178b1d1e | 1754 | } |
wolfSSL | 16:8e0d178b1d1e | 1755 | |
wolfSSL | 16:8e0d178b1d1e | 1756 | if (*outSz < totalSz + SetSequence(totalSz, seq)) { |
wolfSSL | 15:117db924cf7c | 1757 | return BUFFER_E; |
wolfSSL | 15:117db924cf7c | 1758 | } |
wolfSSL | 16:8e0d178b1d1e | 1759 | |
wolfSSL | 16:8e0d178b1d1e | 1760 | idx = 0; |
wolfSSL | 16:8e0d178b1d1e | 1761 | idx += SetSequence(totalSz, out + idx); |
wolfSSL | 16:8e0d178b1d1e | 1762 | idx += SetObjectId(sizeof(WC_PKCS12_ENCRYPTED_OID), out + idx); |
wolfSSL | 16:8e0d178b1d1e | 1763 | if (idx + sizeof(WC_PKCS12_ENCRYPTED_OID) > *outSz){ |
wolfSSL | 16:8e0d178b1d1e | 1764 | return BUFFER_E; |
wolfSSL | 16:8e0d178b1d1e | 1765 | } |
wolfSSL | 16:8e0d178b1d1e | 1766 | XMEMCPY(out + idx, WC_PKCS12_ENCRYPTED_OID, |
wolfSSL | 16:8e0d178b1d1e | 1767 | sizeof(WC_PKCS12_ENCRYPTED_OID)); |
wolfSSL | 16:8e0d178b1d1e | 1768 | idx += sizeof(WC_PKCS12_ENCRYPTED_OID); |
wolfSSL | 16:8e0d178b1d1e | 1769 | |
wolfSSL | 16:8e0d178b1d1e | 1770 | if (idx + 1 > *outSz){ |
wolfSSL | 16:8e0d178b1d1e | 1771 | return BUFFER_E; |
wolfSSL | 16:8e0d178b1d1e | 1772 | } |
wolfSSL | 16:8e0d178b1d1e | 1773 | out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); |
wolfSSL | 16:8e0d178b1d1e | 1774 | idx += SetLength(outerSz, out + idx); |
wolfSSL | 16:8e0d178b1d1e | 1775 | |
wolfSSL | 16:8e0d178b1d1e | 1776 | idx += SetSequence(length, out + idx); |
wolfSSL | 16:8e0d178b1d1e | 1777 | idx += SetMyVersion(0, out + idx, 0); |
wolfSSL | 15:117db924cf7c | 1778 | tmp = (byte*)XMALLOC(encSz, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 15:117db924cf7c | 1779 | if (tmp == NULL) { |
wolfSSL | 15:117db924cf7c | 1780 | return MEMORY_E; |
wolfSSL | 15:117db924cf7c | 1781 | } |
wolfSSL | 15:117db924cf7c | 1782 | |
wolfSSL | 15:117db924cf7c | 1783 | if ((ret = EncryptContent(content, contentSz, tmp, &encSz, |
wolfSSL | 15:117db924cf7c | 1784 | pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) { |
wolfSSL | 15:117db924cf7c | 1785 | XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 15:117db924cf7c | 1786 | return ret; |
wolfSSL | 15:117db924cf7c | 1787 | } |
wolfSSL | 15:117db924cf7c | 1788 | encSz = ret; |
wolfSSL | 15:117db924cf7c | 1789 | |
wolfSSL | 15:117db924cf7c | 1790 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 15:117db924cf7c | 1791 | { |
wolfSSL | 15:117db924cf7c | 1792 | byte* p; |
wolfSSL | 15:117db924cf7c | 1793 | for (printf("(size %u) Encrypted Content = ", encSz), |
wolfSSL | 15:117db924cf7c | 1794 | p = (byte*)tmp; |
wolfSSL | 15:117db924cf7c | 1795 | p < (byte*)tmp + encSz; |
wolfSSL | 15:117db924cf7c | 1796 | printf("%02X", *p), p++); |
wolfSSL | 15:117db924cf7c | 1797 | printf("\n"); |
wolfSSL | 15:117db924cf7c | 1798 | } |
wolfSSL | 15:117db924cf7c | 1799 | #endif |
wolfSSL | 15:117db924cf7c | 1800 | |
wolfSSL | 16:8e0d178b1d1e | 1801 | idx += SetSequence(WC_PKCS12_DATA_OBJ_SZ + encSz, out + idx); |
wolfSSL | 16:8e0d178b1d1e | 1802 | idx += SetObjectId(sizeof(WC_PKCS12_DATA_OID), out + idx); |
wolfSSL | 16:8e0d178b1d1e | 1803 | if (idx + sizeof(WC_PKCS12_DATA_OID) > *outSz){ |
wolfSSL | 16:8e0d178b1d1e | 1804 | WOLFSSL_MSG("Buffer not large enough for DATA OID"); |
wolfSSL | 16:8e0d178b1d1e | 1805 | return BUFFER_E; |
wolfSSL | 15:117db924cf7c | 1806 | } |
wolfSSL | 16:8e0d178b1d1e | 1807 | XMEMCPY(out + idx, WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID)); |
wolfSSL | 16:8e0d178b1d1e | 1808 | idx += sizeof(WC_PKCS12_DATA_OID); |
wolfSSL | 15:117db924cf7c | 1809 | |
wolfSSL | 15:117db924cf7c | 1810 | /* copy over encrypted data */ |
wolfSSL | 16:8e0d178b1d1e | 1811 | if (idx + encSz > *outSz){ |
wolfSSL | 16:8e0d178b1d1e | 1812 | return BUFFER_E; |
wolfSSL | 16:8e0d178b1d1e | 1813 | } |
wolfSSL | 15:117db924cf7c | 1814 | XMEMCPY(out + idx, tmp, encSz); |
wolfSSL | 15:117db924cf7c | 1815 | XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 1816 | idx += encSz; |
wolfSSL | 16:8e0d178b1d1e | 1817 | return idx; |
wolfSSL | 15:117db924cf7c | 1818 | } |
wolfSSL | 15:117db924cf7c | 1819 | |
wolfSSL | 15:117db924cf7c | 1820 | /* DATA |
wolfSSL | 15:117db924cf7c | 1821 | * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC |
wolfSSL | 15:117db924cf7c | 1822 | * length |
wolfSSL | 15:117db924cf7c | 1823 | * ASN_OCTET_STRING |
wolfSSL | 15:117db924cf7c | 1824 | * length |
wolfSSL | 15:117db924cf7c | 1825 | * sequence containing all bags */ |
wolfSSL | 15:117db924cf7c | 1826 | if (type == WC_PKCS12_DATA) { |
wolfSSL | 16:8e0d178b1d1e | 1827 | /* calculate size */ |
wolfSSL | 16:8e0d178b1d1e | 1828 | totalSz = SetObjectId(sizeof(WC_PKCS12_DATA_OID), seq); |
wolfSSL | 16:8e0d178b1d1e | 1829 | totalSz += sizeof(WC_PKCS12_DATA_OID); |
wolfSSL | 16:8e0d178b1d1e | 1830 | totalSz += ASN_TAG_SZ; |
wolfSSL | 16:8e0d178b1d1e | 1831 | |
wolfSSL | 16:8e0d178b1d1e | 1832 | length = SetOctetString(contentSz, seq); |
wolfSSL | 16:8e0d178b1d1e | 1833 | length += contentSz; |
wolfSSL | 16:8e0d178b1d1e | 1834 | totalSz += SetLength(length, seq); |
wolfSSL | 16:8e0d178b1d1e | 1835 | totalSz += length; |
wolfSSL | 16:8e0d178b1d1e | 1836 | |
wolfSSL | 15:117db924cf7c | 1837 | if (out == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 1838 | *outSz = totalSz + SetSequence(totalSz, seq); |
wolfSSL | 15:117db924cf7c | 1839 | return LENGTH_ONLY_E; |
wolfSSL | 15:117db924cf7c | 1840 | } |
wolfSSL | 15:117db924cf7c | 1841 | |
wolfSSL | 16:8e0d178b1d1e | 1842 | if (*outSz < (totalSz + SetSequence(totalSz, seq))) { |
wolfSSL | 15:117db924cf7c | 1843 | return BUFFER_E; |
wolfSSL | 15:117db924cf7c | 1844 | } |
wolfSSL | 15:117db924cf7c | 1845 | |
wolfSSL | 16:8e0d178b1d1e | 1846 | /* place data in output buffer */ |
wolfSSL | 16:8e0d178b1d1e | 1847 | idx = 0; |
wolfSSL | 16:8e0d178b1d1e | 1848 | idx += SetSequence(totalSz, out); |
wolfSSL | 16:8e0d178b1d1e | 1849 | idx += SetObjectId(sizeof(WC_PKCS12_DATA_OID), out + idx); |
wolfSSL | 16:8e0d178b1d1e | 1850 | if (idx + sizeof(WC_PKCS12_DATA_OID) > *outSz){ |
wolfSSL | 16:8e0d178b1d1e | 1851 | WOLFSSL_MSG("Buffer not large enough for DATA OID"); |
wolfSSL | 16:8e0d178b1d1e | 1852 | return BUFFER_E; |
wolfSSL | 16:8e0d178b1d1e | 1853 | } |
wolfSSL | 16:8e0d178b1d1e | 1854 | XMEMCPY(out + idx, WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID)); |
wolfSSL | 16:8e0d178b1d1e | 1855 | idx += sizeof(WC_PKCS12_DATA_OID); |
wolfSSL | 15:117db924cf7c | 1856 | |
wolfSSL | 16:8e0d178b1d1e | 1857 | if (idx + 1 > *outSz){ |
wolfSSL | 16:8e0d178b1d1e | 1858 | return BUFFER_E; |
wolfSSL | 16:8e0d178b1d1e | 1859 | } |
wolfSSL | 16:8e0d178b1d1e | 1860 | out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); |
wolfSSL | 16:8e0d178b1d1e | 1861 | idx += SetLength(length, out + idx); |
wolfSSL | 16:8e0d178b1d1e | 1862 | idx += SetOctetString(contentSz, out + idx); |
wolfSSL | 15:117db924cf7c | 1863 | |
wolfSSL | 16:8e0d178b1d1e | 1864 | if (idx + contentSz > *outSz){ |
wolfSSL | 16:8e0d178b1d1e | 1865 | return BUFFER_E; |
wolfSSL | 16:8e0d178b1d1e | 1866 | } |
wolfSSL | 16:8e0d178b1d1e | 1867 | XMEMCPY(out + idx, content, contentSz); |
wolfSSL | 16:8e0d178b1d1e | 1868 | idx += contentSz; |
wolfSSL | 15:117db924cf7c | 1869 | |
wolfSSL | 16:8e0d178b1d1e | 1870 | return idx; |
wolfSSL | 15:117db924cf7c | 1871 | } |
wolfSSL | 15:117db924cf7c | 1872 | |
wolfSSL | 15:117db924cf7c | 1873 | WOLFSSL_MSG("Unknown/Unsupported content type"); |
wolfSSL | 15:117db924cf7c | 1874 | return BAD_FUNC_ARG; |
wolfSSL | 15:117db924cf7c | 1875 | } |
wolfSSL | 15:117db924cf7c | 1876 | |
wolfSSL | 15:117db924cf7c | 1877 | |
wolfSSL | 16:8e0d178b1d1e | 1878 | /* helper function to create the PKCS12 key content |
wolfSSL | 16:8e0d178b1d1e | 1879 | * keyCiSz is output buffer size |
wolfSSL | 16:8e0d178b1d1e | 1880 | * returns a pointer to be free'd by caller on success and NULL on failure */ |
wolfSSL | 16:8e0d178b1d1e | 1881 | static byte* PKCS12_create_key_content(WC_PKCS12* pkcs12, int nidKey, |
wolfSSL | 16:8e0d178b1d1e | 1882 | word32* keyCiSz, WC_RNG* rng, char* pass, word32 passSz, |
wolfSSL | 16:8e0d178b1d1e | 1883 | byte* key, word32 keySz, int iter) |
wolfSSL | 16:8e0d178b1d1e | 1884 | { |
wolfSSL | 16:8e0d178b1d1e | 1885 | byte* keyBuf; |
wolfSSL | 16:8e0d178b1d1e | 1886 | word32 keyBufSz = 0; |
wolfSSL | 16:8e0d178b1d1e | 1887 | byte* keyCi = NULL; |
wolfSSL | 16:8e0d178b1d1e | 1888 | word32 tmpSz; |
wolfSSL | 16:8e0d178b1d1e | 1889 | int ret; |
wolfSSL | 16:8e0d178b1d1e | 1890 | int algo; |
wolfSSL | 16:8e0d178b1d1e | 1891 | void* heap; |
wolfSSL | 16:8e0d178b1d1e | 1892 | |
wolfSSL | 16:8e0d178b1d1e | 1893 | heap = wc_PKCS12_GetHeap(pkcs12); |
wolfSSL | 16:8e0d178b1d1e | 1894 | *keyCiSz = 0; |
wolfSSL | 16:8e0d178b1d1e | 1895 | switch (nidKey) { |
wolfSSL | 16:8e0d178b1d1e | 1896 | case PBE_SHA1_RC4_128: |
wolfSSL | 16:8e0d178b1d1e | 1897 | algo = 1; |
wolfSSL | 16:8e0d178b1d1e | 1898 | break; |
wolfSSL | 16:8e0d178b1d1e | 1899 | |
wolfSSL | 16:8e0d178b1d1e | 1900 | case PBE_SHA1_DES: |
wolfSSL | 16:8e0d178b1d1e | 1901 | algo = 2; |
wolfSSL | 16:8e0d178b1d1e | 1902 | break; |
wolfSSL | 16:8e0d178b1d1e | 1903 | |
wolfSSL | 16:8e0d178b1d1e | 1904 | case PBE_SHA1_DES3: |
wolfSSL | 16:8e0d178b1d1e | 1905 | algo = 3; |
wolfSSL | 16:8e0d178b1d1e | 1906 | break; |
wolfSSL | 16:8e0d178b1d1e | 1907 | |
wolfSSL | 16:8e0d178b1d1e | 1908 | /* no encryption */ |
wolfSSL | 16:8e0d178b1d1e | 1909 | case -1: |
wolfSSL | 16:8e0d178b1d1e | 1910 | algo = -1; |
wolfSSL | 16:8e0d178b1d1e | 1911 | break; |
wolfSSL | 16:8e0d178b1d1e | 1912 | |
wolfSSL | 16:8e0d178b1d1e | 1913 | default: |
wolfSSL | 16:8e0d178b1d1e | 1914 | WOLFSSL_MSG("Unknown/Unsupported key encryption"); |
wolfSSL | 16:8e0d178b1d1e | 1915 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 1916 | } |
wolfSSL | 16:8e0d178b1d1e | 1917 | |
wolfSSL | 16:8e0d178b1d1e | 1918 | /* get max size for key bag */ |
wolfSSL | 16:8e0d178b1d1e | 1919 | ret = wc_PKCS12_create_key_bag(pkcs12, rng, NULL, &keyBufSz, key, keySz, |
wolfSSL | 16:8e0d178b1d1e | 1920 | algo, iter, pass, passSz); |
wolfSSL | 16:8e0d178b1d1e | 1921 | if (ret != LENGTH_ONLY_E && ret < 0) { |
wolfSSL | 16:8e0d178b1d1e | 1922 | WOLFSSL_MSG("Error getting key bag size"); |
wolfSSL | 16:8e0d178b1d1e | 1923 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 1924 | } |
wolfSSL | 16:8e0d178b1d1e | 1925 | |
wolfSSL | 16:8e0d178b1d1e | 1926 | /* account for sequence around bag */ |
wolfSSL | 16:8e0d178b1d1e | 1927 | keyBufSz += MAX_SEQ_SZ; |
wolfSSL | 16:8e0d178b1d1e | 1928 | keyBuf = (byte*)XMALLOC(keyBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 1929 | if (keyBuf == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 1930 | WOLFSSL_MSG("Memory error creating keyBuf buffer"); |
wolfSSL | 16:8e0d178b1d1e | 1931 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 1932 | } |
wolfSSL | 16:8e0d178b1d1e | 1933 | |
wolfSSL | 16:8e0d178b1d1e | 1934 | ret = wc_PKCS12_create_key_bag(pkcs12, rng, keyBuf + MAX_SEQ_SZ, &keyBufSz, |
wolfSSL | 16:8e0d178b1d1e | 1935 | key, keySz, algo, iter, pass, passSz); |
wolfSSL | 16:8e0d178b1d1e | 1936 | if (ret < 0) { |
wolfSSL | 16:8e0d178b1d1e | 1937 | XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 1938 | WOLFSSL_MSG("Error creating key bag"); |
wolfSSL | 16:8e0d178b1d1e | 1939 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 1940 | } |
wolfSSL | 16:8e0d178b1d1e | 1941 | keyBufSz = ret; |
wolfSSL | 16:8e0d178b1d1e | 1942 | |
wolfSSL | 16:8e0d178b1d1e | 1943 | tmpSz = SetSequence(keyBufSz, keyBuf); |
wolfSSL | 16:8e0d178b1d1e | 1944 | XMEMMOVE(keyBuf + tmpSz, keyBuf + MAX_SEQ_SZ, keyBufSz); |
wolfSSL | 16:8e0d178b1d1e | 1945 | keyBufSz += tmpSz; |
wolfSSL | 16:8e0d178b1d1e | 1946 | |
wolfSSL | 16:8e0d178b1d1e | 1947 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 16:8e0d178b1d1e | 1948 | { |
wolfSSL | 16:8e0d178b1d1e | 1949 | word32 i; |
wolfSSL | 16:8e0d178b1d1e | 1950 | printf("(size %u) Key Bag = ", keyBufSz); |
wolfSSL | 16:8e0d178b1d1e | 1951 | for (i = 0; i < keyBufSz; i++) |
wolfSSL | 16:8e0d178b1d1e | 1952 | printf("%02X", keyBuf[i]); |
wolfSSL | 16:8e0d178b1d1e | 1953 | printf("\n"); |
wolfSSL | 16:8e0d178b1d1e | 1954 | } |
wolfSSL | 16:8e0d178b1d1e | 1955 | #endif |
wolfSSL | 16:8e0d178b1d1e | 1956 | ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, keyCiSz, |
wolfSSL | 16:8e0d178b1d1e | 1957 | NULL, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA); |
wolfSSL | 16:8e0d178b1d1e | 1958 | if (ret != LENGTH_ONLY_E) { |
wolfSSL | 16:8e0d178b1d1e | 1959 | XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 1960 | WOLFSSL_MSG("Error getting key encrypt content size"); |
wolfSSL | 16:8e0d178b1d1e | 1961 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 1962 | } |
wolfSSL | 16:8e0d178b1d1e | 1963 | keyCi = (byte*)XMALLOC(*keyCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 1964 | if (keyCi == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 1965 | XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 1966 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 1967 | } |
wolfSSL | 16:8e0d178b1d1e | 1968 | |
wolfSSL | 16:8e0d178b1d1e | 1969 | ret = wc_PKCS12_encrypt_content(pkcs12, rng, keyCi, keyCiSz, |
wolfSSL | 16:8e0d178b1d1e | 1970 | keyBuf, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA); |
wolfSSL | 16:8e0d178b1d1e | 1971 | XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 1972 | if (ret < 0 ) { |
wolfSSL | 16:8e0d178b1d1e | 1973 | XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 1974 | WOLFSSL_MSG("Error creating key encrypt content"); |
wolfSSL | 16:8e0d178b1d1e | 1975 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 1976 | } |
wolfSSL | 16:8e0d178b1d1e | 1977 | *keyCiSz = ret; |
wolfSSL | 16:8e0d178b1d1e | 1978 | |
wolfSSL | 16:8e0d178b1d1e | 1979 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 16:8e0d178b1d1e | 1980 | { |
wolfSSL | 16:8e0d178b1d1e | 1981 | word32 i; |
wolfSSL | 16:8e0d178b1d1e | 1982 | printf("(size %u) Key Content Info = ", *keyCiSz); |
wolfSSL | 16:8e0d178b1d1e | 1983 | for (i = 0; i < *keyCiSz; i++) |
wolfSSL | 16:8e0d178b1d1e | 1984 | printf("%02X", keyCi[i]); |
wolfSSL | 16:8e0d178b1d1e | 1985 | printf("\n"); |
wolfSSL | 16:8e0d178b1d1e | 1986 | } |
wolfSSL | 16:8e0d178b1d1e | 1987 | #endif |
wolfSSL | 16:8e0d178b1d1e | 1988 | |
wolfSSL | 16:8e0d178b1d1e | 1989 | (void)heap; |
wolfSSL | 16:8e0d178b1d1e | 1990 | return keyCi; |
wolfSSL | 16:8e0d178b1d1e | 1991 | } |
wolfSSL | 16:8e0d178b1d1e | 1992 | |
wolfSSL | 16:8e0d178b1d1e | 1993 | |
wolfSSL | 16:8e0d178b1d1e | 1994 | /* helper function to create the PKCS12 certificate content |
wolfSSL | 16:8e0d178b1d1e | 1995 | * certCiSz is output buffer size |
wolfSSL | 16:8e0d178b1d1e | 1996 | * returns a pointer to be free'd by caller on success and NULL on failure */ |
wolfSSL | 16:8e0d178b1d1e | 1997 | static byte* PKCS12_create_cert_content(WC_PKCS12* pkcs12, int nidCert, |
wolfSSL | 16:8e0d178b1d1e | 1998 | WC_DerCertList* ca, byte* cert, word32 certSz, word32* certCiSz, |
wolfSSL | 16:8e0d178b1d1e | 1999 | WC_RNG* rng, char* pass, word32 passSz, int iter) |
wolfSSL | 16:8e0d178b1d1e | 2000 | { |
wolfSSL | 16:8e0d178b1d1e | 2001 | int algo; |
wolfSSL | 16:8e0d178b1d1e | 2002 | int ret; |
wolfSSL | 16:8e0d178b1d1e | 2003 | int type; |
wolfSSL | 16:8e0d178b1d1e | 2004 | |
wolfSSL | 16:8e0d178b1d1e | 2005 | byte* certBuf = NULL; |
wolfSSL | 16:8e0d178b1d1e | 2006 | word32 certBufSz; |
wolfSSL | 16:8e0d178b1d1e | 2007 | word32 idx; |
wolfSSL | 16:8e0d178b1d1e | 2008 | word32 sz; |
wolfSSL | 16:8e0d178b1d1e | 2009 | word32 tmpSz; |
wolfSSL | 16:8e0d178b1d1e | 2010 | |
wolfSSL | 16:8e0d178b1d1e | 2011 | byte* certCi; |
wolfSSL | 16:8e0d178b1d1e | 2012 | void* heap; |
wolfSSL | 16:8e0d178b1d1e | 2013 | |
wolfSSL | 16:8e0d178b1d1e | 2014 | heap = wc_PKCS12_GetHeap(pkcs12); |
wolfSSL | 16:8e0d178b1d1e | 2015 | switch (nidCert) { |
wolfSSL | 16:8e0d178b1d1e | 2016 | case PBE_SHA1_RC4_128: |
wolfSSL | 16:8e0d178b1d1e | 2017 | type = WC_PKCS12_ENCRYPTED_DATA; |
wolfSSL | 16:8e0d178b1d1e | 2018 | algo = 1; |
wolfSSL | 16:8e0d178b1d1e | 2019 | break; |
wolfSSL | 16:8e0d178b1d1e | 2020 | |
wolfSSL | 16:8e0d178b1d1e | 2021 | case PBE_SHA1_DES: |
wolfSSL | 16:8e0d178b1d1e | 2022 | type = WC_PKCS12_ENCRYPTED_DATA; |
wolfSSL | 16:8e0d178b1d1e | 2023 | algo = 2; |
wolfSSL | 16:8e0d178b1d1e | 2024 | break; |
wolfSSL | 16:8e0d178b1d1e | 2025 | |
wolfSSL | 16:8e0d178b1d1e | 2026 | case PBE_SHA1_DES3: |
wolfSSL | 16:8e0d178b1d1e | 2027 | type = WC_PKCS12_ENCRYPTED_DATA; |
wolfSSL | 16:8e0d178b1d1e | 2028 | algo = 3; |
wolfSSL | 16:8e0d178b1d1e | 2029 | break; |
wolfSSL | 16:8e0d178b1d1e | 2030 | |
wolfSSL | 16:8e0d178b1d1e | 2031 | case -1: |
wolfSSL | 16:8e0d178b1d1e | 2032 | type = WC_PKCS12_DATA; |
wolfSSL | 16:8e0d178b1d1e | 2033 | algo = -1; |
wolfSSL | 16:8e0d178b1d1e | 2034 | break; |
wolfSSL | 16:8e0d178b1d1e | 2035 | |
wolfSSL | 16:8e0d178b1d1e | 2036 | default: |
wolfSSL | 16:8e0d178b1d1e | 2037 | WOLFSSL_MSG("Unknown/Unsupported certificate encryption"); |
wolfSSL | 16:8e0d178b1d1e | 2038 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 2039 | } |
wolfSSL | 16:8e0d178b1d1e | 2040 | |
wolfSSL | 16:8e0d178b1d1e | 2041 | /* get max size of buffer needed */ |
wolfSSL | 16:8e0d178b1d1e | 2042 | ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &certBufSz, cert, certSz); |
wolfSSL | 16:8e0d178b1d1e | 2043 | if (ret != LENGTH_ONLY_E) { |
wolfSSL | 16:8e0d178b1d1e | 2044 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 2045 | } |
wolfSSL | 16:8e0d178b1d1e | 2046 | |
wolfSSL | 16:8e0d178b1d1e | 2047 | if (ca != NULL) { |
wolfSSL | 16:8e0d178b1d1e | 2048 | WC_DerCertList* current = ca; |
wolfSSL | 16:8e0d178b1d1e | 2049 | word32 curBufSz = 0; |
wolfSSL | 16:8e0d178b1d1e | 2050 | |
wolfSSL | 16:8e0d178b1d1e | 2051 | /* get max buffer size */ |
wolfSSL | 16:8e0d178b1d1e | 2052 | while (current != NULL) { |
wolfSSL | 16:8e0d178b1d1e | 2053 | ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &curBufSz, |
wolfSSL | 16:8e0d178b1d1e | 2054 | current->buffer, current->bufferSz); |
wolfSSL | 16:8e0d178b1d1e | 2055 | if (ret != LENGTH_ONLY_E) { |
wolfSSL | 16:8e0d178b1d1e | 2056 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 2057 | } |
wolfSSL | 16:8e0d178b1d1e | 2058 | certBufSz += curBufSz; |
wolfSSL | 16:8e0d178b1d1e | 2059 | current = current->next; |
wolfSSL | 16:8e0d178b1d1e | 2060 | } |
wolfSSL | 16:8e0d178b1d1e | 2061 | } |
wolfSSL | 16:8e0d178b1d1e | 2062 | |
wolfSSL | 16:8e0d178b1d1e | 2063 | /* account for Sequence that holds all certificate bags */ |
wolfSSL | 16:8e0d178b1d1e | 2064 | certBufSz += MAX_SEQ_SZ; |
wolfSSL | 16:8e0d178b1d1e | 2065 | |
wolfSSL | 16:8e0d178b1d1e | 2066 | /* completed getting max size, now create buffer and start adding bags */ |
wolfSSL | 16:8e0d178b1d1e | 2067 | certBuf = (byte*)XMALLOC(certBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2068 | if (certBuf == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 2069 | WOLFSSL_MSG("Memory error creating certificate bags"); |
wolfSSL | 16:8e0d178b1d1e | 2070 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 2071 | } |
wolfSSL | 16:8e0d178b1d1e | 2072 | |
wolfSSL | 16:8e0d178b1d1e | 2073 | idx = 0; |
wolfSSL | 16:8e0d178b1d1e | 2074 | idx += MAX_SEQ_SZ; |
wolfSSL | 16:8e0d178b1d1e | 2075 | |
wolfSSL | 16:8e0d178b1d1e | 2076 | sz = certBufSz - idx; |
wolfSSL | 16:8e0d178b1d1e | 2077 | if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz, |
wolfSSL | 16:8e0d178b1d1e | 2078 | cert, certSz)) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 2079 | XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2080 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 2081 | } |
wolfSSL | 16:8e0d178b1d1e | 2082 | idx += ret; |
wolfSSL | 16:8e0d178b1d1e | 2083 | |
wolfSSL | 16:8e0d178b1d1e | 2084 | if (ca != NULL) { |
wolfSSL | 16:8e0d178b1d1e | 2085 | WC_DerCertList* current = ca; |
wolfSSL | 16:8e0d178b1d1e | 2086 | |
wolfSSL | 16:8e0d178b1d1e | 2087 | while (current != NULL) { |
wolfSSL | 16:8e0d178b1d1e | 2088 | sz = certBufSz - idx; |
wolfSSL | 16:8e0d178b1d1e | 2089 | if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz, |
wolfSSL | 16:8e0d178b1d1e | 2090 | current->buffer, current->bufferSz)) < 0) { |
wolfSSL | 16:8e0d178b1d1e | 2091 | XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2092 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 2093 | } |
wolfSSL | 16:8e0d178b1d1e | 2094 | idx += ret; |
wolfSSL | 16:8e0d178b1d1e | 2095 | current = current->next; |
wolfSSL | 16:8e0d178b1d1e | 2096 | } |
wolfSSL | 16:8e0d178b1d1e | 2097 | } |
wolfSSL | 16:8e0d178b1d1e | 2098 | |
wolfSSL | 16:8e0d178b1d1e | 2099 | /* set sequence and create encrypted content with all certificate bags */ |
wolfSSL | 16:8e0d178b1d1e | 2100 | tmpSz = SetSequence(idx - MAX_SEQ_SZ, certBuf); |
wolfSSL | 16:8e0d178b1d1e | 2101 | XMEMMOVE(certBuf + tmpSz, certBuf + MAX_SEQ_SZ, idx - MAX_SEQ_SZ); |
wolfSSL | 16:8e0d178b1d1e | 2102 | certBufSz = tmpSz + (idx - MAX_SEQ_SZ); |
wolfSSL | 16:8e0d178b1d1e | 2103 | |
wolfSSL | 16:8e0d178b1d1e | 2104 | /* get buffer size needed for content info */ |
wolfSSL | 16:8e0d178b1d1e | 2105 | ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, certCiSz, |
wolfSSL | 16:8e0d178b1d1e | 2106 | NULL, certBufSz, algo, pass, passSz, iter, type); |
wolfSSL | 16:8e0d178b1d1e | 2107 | if (ret != LENGTH_ONLY_E) { |
wolfSSL | 16:8e0d178b1d1e | 2108 | XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2109 | WOLFSSL_LEAVE("wc_PKCS12_create()", ret); |
wolfSSL | 16:8e0d178b1d1e | 2110 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 2111 | } |
wolfSSL | 16:8e0d178b1d1e | 2112 | certCi = (byte*)XMALLOC(*certCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2113 | if (certCi == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 2114 | XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2115 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 2116 | } |
wolfSSL | 16:8e0d178b1d1e | 2117 | |
wolfSSL | 16:8e0d178b1d1e | 2118 | ret = wc_PKCS12_encrypt_content(pkcs12, rng, certCi, certCiSz, |
wolfSSL | 16:8e0d178b1d1e | 2119 | certBuf, certBufSz, algo, pass, passSz, iter, type); |
wolfSSL | 16:8e0d178b1d1e | 2120 | XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2121 | if (ret < 0) { |
wolfSSL | 16:8e0d178b1d1e | 2122 | WOLFSSL_LEAVE("wc_PKCS12_create()", ret); |
wolfSSL | 16:8e0d178b1d1e | 2123 | return NULL; |
wolfSSL | 16:8e0d178b1d1e | 2124 | } |
wolfSSL | 16:8e0d178b1d1e | 2125 | *certCiSz = ret; |
wolfSSL | 16:8e0d178b1d1e | 2126 | |
wolfSSL | 16:8e0d178b1d1e | 2127 | #ifdef WOLFSSL_DEBUG_PKCS12 |
wolfSSL | 16:8e0d178b1d1e | 2128 | { |
wolfSSL | 16:8e0d178b1d1e | 2129 | word32 i; |
wolfSSL | 16:8e0d178b1d1e | 2130 | printf("(size %u) Encrypted Certificate Content Info = ", *certCiSz); |
wolfSSL | 16:8e0d178b1d1e | 2131 | for (i = 0; i < *certCiSz; i++) |
wolfSSL | 16:8e0d178b1d1e | 2132 | printf("%02X", certCi[i]); |
wolfSSL | 16:8e0d178b1d1e | 2133 | printf("\n"); |
wolfSSL | 16:8e0d178b1d1e | 2134 | } |
wolfSSL | 16:8e0d178b1d1e | 2135 | #endif |
wolfSSL | 16:8e0d178b1d1e | 2136 | |
wolfSSL | 16:8e0d178b1d1e | 2137 | (void)heap; |
wolfSSL | 16:8e0d178b1d1e | 2138 | return certCi; |
wolfSSL | 16:8e0d178b1d1e | 2139 | } |
wolfSSL | 16:8e0d178b1d1e | 2140 | |
wolfSSL | 16:8e0d178b1d1e | 2141 | |
wolfSSL | 16:8e0d178b1d1e | 2142 | /* helper function to create the PKCS12 safe |
wolfSSL | 16:8e0d178b1d1e | 2143 | * returns 0 on success */ |
wolfSSL | 16:8e0d178b1d1e | 2144 | static int PKCS12_create_safe(WC_PKCS12* pkcs12, byte* certCi, word32 certCiSz, |
wolfSSL | 16:8e0d178b1d1e | 2145 | byte* keyCi, word32 keyCiSz, WC_RNG* rng, char* pass, word32 passSz, |
wolfSSL | 16:8e0d178b1d1e | 2146 | int iter) |
wolfSSL | 16:8e0d178b1d1e | 2147 | { |
wolfSSL | 16:8e0d178b1d1e | 2148 | int length; |
wolfSSL | 16:8e0d178b1d1e | 2149 | int ret; |
wolfSSL | 16:8e0d178b1d1e | 2150 | byte seq[MAX_SEQ_SZ]; |
wolfSSL | 16:8e0d178b1d1e | 2151 | word32 safeDataSz; |
wolfSSL | 16:8e0d178b1d1e | 2152 | word32 innerDataSz; |
wolfSSL | 16:8e0d178b1d1e | 2153 | byte *innerData = NULL; |
wolfSSL | 16:8e0d178b1d1e | 2154 | byte *safeData = NULL; |
wolfSSL | 16:8e0d178b1d1e | 2155 | word32 idx; |
wolfSSL | 16:8e0d178b1d1e | 2156 | |
wolfSSL | 16:8e0d178b1d1e | 2157 | innerDataSz = certCiSz + keyCiSz+SetSequence(certCiSz + keyCiSz, seq); |
wolfSSL | 16:8e0d178b1d1e | 2158 | |
wolfSSL | 16:8e0d178b1d1e | 2159 | /* add Content Info structs to safe, key first then cert */ |
wolfSSL | 16:8e0d178b1d1e | 2160 | ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, &safeDataSz, |
wolfSSL | 16:8e0d178b1d1e | 2161 | NULL, innerDataSz, 0, NULL, 0, 0, WC_PKCS12_DATA); |
wolfSSL | 16:8e0d178b1d1e | 2162 | if (ret != LENGTH_ONLY_E) { |
wolfSSL | 16:8e0d178b1d1e | 2163 | return ret; |
wolfSSL | 16:8e0d178b1d1e | 2164 | } |
wolfSSL | 16:8e0d178b1d1e | 2165 | |
wolfSSL | 16:8e0d178b1d1e | 2166 | safeData = (byte*)XMALLOC(safeDataSz, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2167 | if (safeData == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 2168 | WOLFSSL_MSG("Error malloc'ing safe data buffer"); |
wolfSSL | 16:8e0d178b1d1e | 2169 | return MEMORY_E; |
wolfSSL | 16:8e0d178b1d1e | 2170 | } |
wolfSSL | 16:8e0d178b1d1e | 2171 | |
wolfSSL | 16:8e0d178b1d1e | 2172 | /* create sequence of inner data */ |
wolfSSL | 16:8e0d178b1d1e | 2173 | innerData = (byte*)XMALLOC(innerDataSz, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 16:8e0d178b1d1e | 2174 | if (innerData == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 2175 | WOLFSSL_MSG("Error malloc'ing inner data buffer"); |
wolfSSL | 16:8e0d178b1d1e | 2176 | XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2177 | return MEMORY_E; |
wolfSSL | 16:8e0d178b1d1e | 2178 | } |
wolfSSL | 16:8e0d178b1d1e | 2179 | idx = 0; |
wolfSSL | 16:8e0d178b1d1e | 2180 | idx += SetSequence(certCiSz + keyCiSz, innerData); |
wolfSSL | 16:8e0d178b1d1e | 2181 | XMEMCPY(innerData + idx, certCi, certCiSz); |
wolfSSL | 16:8e0d178b1d1e | 2182 | XMEMCPY(innerData + idx + certCiSz, keyCi, keyCiSz); |
wolfSSL | 16:8e0d178b1d1e | 2183 | |
wolfSSL | 16:8e0d178b1d1e | 2184 | ret = wc_PKCS12_encrypt_content(pkcs12, rng, safeData, &safeDataSz, |
wolfSSL | 16:8e0d178b1d1e | 2185 | innerData, innerDataSz, 0, pass, passSz, iter, WC_PKCS12_DATA); |
wolfSSL | 16:8e0d178b1d1e | 2186 | XFREE(innerData, pkcs12->heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 16:8e0d178b1d1e | 2187 | if (ret < 0 ) { |
wolfSSL | 16:8e0d178b1d1e | 2188 | WOLFSSL_MSG("Error setting data type for safe contents"); |
wolfSSL | 16:8e0d178b1d1e | 2189 | XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2190 | return ret; |
wolfSSL | 16:8e0d178b1d1e | 2191 | } |
wolfSSL | 16:8e0d178b1d1e | 2192 | idx = 0; |
wolfSSL | 16:8e0d178b1d1e | 2193 | |
wolfSSL | 16:8e0d178b1d1e | 2194 | ret = GetSequence(safeData, &idx, &length, safeDataSz); |
wolfSSL | 16:8e0d178b1d1e | 2195 | if (ret < 0) { |
wolfSSL | 16:8e0d178b1d1e | 2196 | WOLFSSL_MSG("Error getting first sequence of safe"); |
wolfSSL | 16:8e0d178b1d1e | 2197 | XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2198 | return ret; |
wolfSSL | 16:8e0d178b1d1e | 2199 | } |
wolfSSL | 16:8e0d178b1d1e | 2200 | |
wolfSSL | 16:8e0d178b1d1e | 2201 | ret = GetSafeContent(pkcs12, safeData, &idx, safeDataSz); |
wolfSSL | 16:8e0d178b1d1e | 2202 | XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2203 | if (ret < 0) { |
wolfSSL | 16:8e0d178b1d1e | 2204 | WOLFSSL_MSG("Unable to create safe contents"); |
wolfSSL | 16:8e0d178b1d1e | 2205 | return ret; |
wolfSSL | 16:8e0d178b1d1e | 2206 | } |
wolfSSL | 16:8e0d178b1d1e | 2207 | return 0; |
wolfSSL | 16:8e0d178b1d1e | 2208 | } |
wolfSSL | 16:8e0d178b1d1e | 2209 | |
wolfSSL | 16:8e0d178b1d1e | 2210 | |
wolfSSL | 15:117db924cf7c | 2211 | /* |
wolfSSL | 15:117db924cf7c | 2212 | * pass : password to use with encryption |
wolfSSL | 15:117db924cf7c | 2213 | * passSz : size of the password buffer |
wolfSSL | 15:117db924cf7c | 2214 | * name : friendlyName to use |
wolfSSL | 15:117db924cf7c | 2215 | * key : DER format of key |
wolfSSL | 15:117db924cf7c | 2216 | * keySz : size of key buffer |
wolfSSL | 15:117db924cf7c | 2217 | * cert : DER format of certificate |
wolfSSL | 15:117db924cf7c | 2218 | * certSz : size of the certificate buffer |
wolfSSL | 15:117db924cf7c | 2219 | * ca : a list of extra certificates |
wolfSSL | 15:117db924cf7c | 2220 | * nidKey : type of encryption to use on the key (-1 means no encryption) |
wolfSSL | 15:117db924cf7c | 2221 | * nidCert : type of encryption to use on the certificate |
wolfSSL | 15:117db924cf7c | 2222 | * (-1 means no encryption) |
wolfSSL | 15:117db924cf7c | 2223 | * iter : number of iterations with encryption |
wolfSSL | 15:117db924cf7c | 2224 | * macIter : number of iterations when creating MAC |
wolfSSL | 15:117db924cf7c | 2225 | * keyType : flag for signature and/or encryption key |
wolfSSL | 15:117db924cf7c | 2226 | * heap : pointer to allocate from memory |
wolfSSL | 15:117db924cf7c | 2227 | * |
wolfSSL | 15:117db924cf7c | 2228 | * returns a pointer to a new WC_PKCS12 structure on success and NULL if failed |
wolfSSL | 15:117db924cf7c | 2229 | */ |
wolfSSL | 15:117db924cf7c | 2230 | WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name, |
wolfSSL | 15:117db924cf7c | 2231 | byte* key, word32 keySz, byte* cert, word32 certSz, WC_DerCertList* ca, |
wolfSSL | 15:117db924cf7c | 2232 | int nidKey, int nidCert, int iter, int macIter, int keyType, void* heap) |
wolfSSL | 15:117db924cf7c | 2233 | { |
wolfSSL | 16:8e0d178b1d1e | 2234 | WC_PKCS12* pkcs12; |
wolfSSL | 16:8e0d178b1d1e | 2235 | WC_RNG rng; |
wolfSSL | 15:117db924cf7c | 2236 | int ret; |
wolfSSL | 15:117db924cf7c | 2237 | |
wolfSSL | 15:117db924cf7c | 2238 | byte* certCi = NULL; |
wolfSSL | 16:8e0d178b1d1e | 2239 | byte* keyCi = NULL; |
wolfSSL | 15:117db924cf7c | 2240 | word32 certCiSz; |
wolfSSL | 15:117db924cf7c | 2241 | word32 keyCiSz; |
wolfSSL | 15:117db924cf7c | 2242 | |
wolfSSL | 15:117db924cf7c | 2243 | WOLFSSL_ENTER("wc_PKCS12_create()"); |
wolfSSL | 15:117db924cf7c | 2244 | |
wolfSSL | 15:117db924cf7c | 2245 | if ((ret = wc_InitRng_ex(&rng, heap, INVALID_DEVID)) != 0) { |
wolfSSL | 15:117db924cf7c | 2246 | return NULL; |
wolfSSL | 15:117db924cf7c | 2247 | } |
wolfSSL | 15:117db924cf7c | 2248 | |
wolfSSL | 15:117db924cf7c | 2249 | if ((pkcs12 = wc_PKCS12_new()) == NULL) { |
wolfSSL | 15:117db924cf7c | 2250 | wc_FreeRng(&rng); |
wolfSSL | 15:117db924cf7c | 2251 | WOLFSSL_LEAVE("wc_PKCS12_create", MEMORY_E); |
wolfSSL | 15:117db924cf7c | 2252 | return NULL; |
wolfSSL | 15:117db924cf7c | 2253 | } |
wolfSSL | 15:117db924cf7c | 2254 | |
wolfSSL | 15:117db924cf7c | 2255 | if ((ret = wc_PKCS12_SetHeap(pkcs12, heap)) != 0) { |
wolfSSL | 15:117db924cf7c | 2256 | wc_PKCS12_free(pkcs12); |
wolfSSL | 15:117db924cf7c | 2257 | wc_FreeRng(&rng); |
wolfSSL | 15:117db924cf7c | 2258 | WOLFSSL_LEAVE("wc_PKCS12_create", ret); |
wolfSSL | 15:117db924cf7c | 2259 | return NULL; |
wolfSSL | 15:117db924cf7c | 2260 | } |
wolfSSL | 15:117db924cf7c | 2261 | |
wolfSSL | 15:117db924cf7c | 2262 | if (iter <= 0) { |
wolfSSL | 15:117db924cf7c | 2263 | iter = WC_PKCS12_ITT_DEFAULT; |
wolfSSL | 15:117db924cf7c | 2264 | } |
wolfSSL | 15:117db924cf7c | 2265 | |
wolfSSL | 15:117db924cf7c | 2266 | /**** add private key bag ****/ |
wolfSSL | 16:8e0d178b1d1e | 2267 | keyCi = PKCS12_create_key_content(pkcs12, nidKey, &keyCiSz, &rng, |
wolfSSL | 16:8e0d178b1d1e | 2268 | pass, passSz, key, keySz, iter); |
wolfSSL | 16:8e0d178b1d1e | 2269 | if (keyCi == NULL) { |
wolfSSL | 15:117db924cf7c | 2270 | wc_PKCS12_free(pkcs12); |
wolfSSL | 15:117db924cf7c | 2271 | wc_FreeRng(&rng); |
wolfSSL | 15:117db924cf7c | 2272 | return NULL; |
wolfSSL | 15:117db924cf7c | 2273 | } |
wolfSSL | 15:117db924cf7c | 2274 | |
wolfSSL | 15:117db924cf7c | 2275 | /**** add main certificate bag and extras ****/ |
wolfSSL | 16:8e0d178b1d1e | 2276 | certCi = PKCS12_create_cert_content(pkcs12, nidCert, ca, cert, certSz, |
wolfSSL | 16:8e0d178b1d1e | 2277 | &certCiSz, &rng, pass, passSz, iter); |
wolfSSL | 16:8e0d178b1d1e | 2278 | if (certCi == NULL) { |
wolfSSL | 15:117db924cf7c | 2279 | XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 15:117db924cf7c | 2280 | wc_PKCS12_free(pkcs12); |
wolfSSL | 15:117db924cf7c | 2281 | wc_FreeRng(&rng); |
wolfSSL | 15:117db924cf7c | 2282 | return NULL; |
wolfSSL | 15:117db924cf7c | 2283 | } |
wolfSSL | 15:117db924cf7c | 2284 | |
wolfSSL | 16:8e0d178b1d1e | 2285 | /**** create safe and Content Info ****/ |
wolfSSL | 16:8e0d178b1d1e | 2286 | ret = PKCS12_create_safe(pkcs12, certCi, certCiSz, keyCi, keyCiSz, &rng, |
wolfSSL | 16:8e0d178b1d1e | 2287 | pass, passSz, iter); |
wolfSSL | 16:8e0d178b1d1e | 2288 | XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2289 | XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); |
wolfSSL | 16:8e0d178b1d1e | 2290 | if (ret != 0) { |
wolfSSL | 16:8e0d178b1d1e | 2291 | WOLFSSL_MSG("Unable to create PKCS12 safe"); |
wolfSSL | 15:117db924cf7c | 2292 | wc_PKCS12_free(pkcs12); |
wolfSSL | 15:117db924cf7c | 2293 | wc_FreeRng(&rng); |
wolfSSL | 15:117db924cf7c | 2294 | return NULL; |
wolfSSL | 15:117db924cf7c | 2295 | } |
wolfSSL | 15:117db924cf7c | 2296 | |
wolfSSL | 15:117db924cf7c | 2297 | /* create MAC */ |
wolfSSL | 15:117db924cf7c | 2298 | if (macIter > 0) { |
wolfSSL | 15:117db924cf7c | 2299 | MacData* mac; |
wolfSSL | 15:117db924cf7c | 2300 | byte digest[WC_MAX_DIGEST_SIZE]; /* for MAC */ |
wolfSSL | 15:117db924cf7c | 2301 | |
wolfSSL | 15:117db924cf7c | 2302 | mac = (MacData*)XMALLOC(sizeof(MacData), heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 2303 | if (mac == NULL) { |
wolfSSL | 15:117db924cf7c | 2304 | wc_PKCS12_free(pkcs12); |
wolfSSL | 15:117db924cf7c | 2305 | wc_FreeRng(&rng); |
wolfSSL | 16:8e0d178b1d1e | 2306 | WOLFSSL_MSG("Error malloc'ing mac data buffer"); |
wolfSSL | 15:117db924cf7c | 2307 | return NULL; |
wolfSSL | 15:117db924cf7c | 2308 | } |
wolfSSL | 15:117db924cf7c | 2309 | XMEMSET(mac, 0, sizeof(MacData)); |
wolfSSL | 15:117db924cf7c | 2310 | pkcs12->signData = mac; /* now wc_PKCS12_free will free all mac too */ |
wolfSSL | 15:117db924cf7c | 2311 | |
wolfSSL | 15:117db924cf7c | 2312 | #ifndef NO_SHA256 |
wolfSSL | 15:117db924cf7c | 2313 | mac->oid = SHA256h; |
wolfSSL | 15:117db924cf7c | 2314 | #elif !defined(NO_SHA) |
wolfSSL | 15:117db924cf7c | 2315 | mac->oid = SHA; |
wolfSSL | 15:117db924cf7c | 2316 | #elif defined(WOLFSSL_SHA384) |
wolfSSL | 15:117db924cf7c | 2317 | mac->oid = SHA384; |
wolfSSL | 15:117db924cf7c | 2318 | #elif defined(WOLFSSL_SHA512) |
wolfSSL | 15:117db924cf7c | 2319 | mac->oid = SHA512; |
wolfSSL | 15:117db924cf7c | 2320 | #else |
wolfSSL | 15:117db924cf7c | 2321 | WOLFSSL_MSG("No supported hash algorithm compiled in!"); |
wolfSSL | 15:117db924cf7c | 2322 | wc_PKCS12_free(pkcs12); |
wolfSSL | 15:117db924cf7c | 2323 | wc_FreeRng(&rng); |
wolfSSL | 15:117db924cf7c | 2324 | return NULL; |
wolfSSL | 15:117db924cf7c | 2325 | #endif |
wolfSSL | 15:117db924cf7c | 2326 | |
wolfSSL | 15:117db924cf7c | 2327 | /* store number of iterations */ |
wolfSSL | 15:117db924cf7c | 2328 | mac->itt = macIter; |
wolfSSL | 15:117db924cf7c | 2329 | |
wolfSSL | 15:117db924cf7c | 2330 | /* set mac salt */ |
wolfSSL | 15:117db924cf7c | 2331 | mac->saltSz = 8; |
wolfSSL | 15:117db924cf7c | 2332 | mac->salt = (byte*)XMALLOC(mac->saltSz, heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 2333 | if (mac->salt == NULL) { |
wolfSSL | 15:117db924cf7c | 2334 | wc_PKCS12_free(pkcs12); |
wolfSSL | 15:117db924cf7c | 2335 | wc_FreeRng(&rng); |
wolfSSL | 16:8e0d178b1d1e | 2336 | WOLFSSL_MSG("Error malloc'ing salt data buffer"); |
wolfSSL | 15:117db924cf7c | 2337 | return NULL; |
wolfSSL | 15:117db924cf7c | 2338 | } |
wolfSSL | 15:117db924cf7c | 2339 | |
wolfSSL | 15:117db924cf7c | 2340 | if ((ret = wc_RNG_GenerateBlock(&rng, mac->salt, mac->saltSz)) != 0) { |
wolfSSL | 15:117db924cf7c | 2341 | WOLFSSL_MSG("Error generating random salt"); |
wolfSSL | 15:117db924cf7c | 2342 | wc_PKCS12_free(pkcs12); |
wolfSSL | 15:117db924cf7c | 2343 | wc_FreeRng(&rng); |
wolfSSL | 15:117db924cf7c | 2344 | return NULL; |
wolfSSL | 15:117db924cf7c | 2345 | } |
wolfSSL | 16:8e0d178b1d1e | 2346 | ret = wc_PKCS12_create_mac(pkcs12, pkcs12->safe->data, |
wolfSSL | 16:8e0d178b1d1e | 2347 | pkcs12->safe->dataSz, (const byte*)pass, passSz, digest, |
wolfSSL | 16:8e0d178b1d1e | 2348 | WC_MAX_DIGEST_SIZE); |
wolfSSL | 15:117db924cf7c | 2349 | if (ret < 0) { |
wolfSSL | 15:117db924cf7c | 2350 | wc_PKCS12_free(pkcs12); |
wolfSSL | 15:117db924cf7c | 2351 | wc_FreeRng(&rng); |
wolfSSL | 16:8e0d178b1d1e | 2352 | WOLFSSL_MSG("Error creating mac"); |
wolfSSL | 16:8e0d178b1d1e | 2353 | WOLFSSL_LEAVE("wc_PKCS12_create", ret); |
wolfSSL | 15:117db924cf7c | 2354 | return NULL; |
wolfSSL | 15:117db924cf7c | 2355 | } |
wolfSSL | 15:117db924cf7c | 2356 | |
wolfSSL | 15:117db924cf7c | 2357 | mac->digestSz = ret; |
wolfSSL | 15:117db924cf7c | 2358 | mac->digest = (byte*)XMALLOC(ret, heap, DYNAMIC_TYPE_PKCS); |
wolfSSL | 15:117db924cf7c | 2359 | if (mac->digest == NULL) { |
wolfSSL | 16:8e0d178b1d1e | 2360 | WOLFSSL_MSG("Error malloc'ing mac digest buffer"); |
wolfSSL | 15:117db924cf7c | 2361 | wc_PKCS12_free(pkcs12); |
wolfSSL | 15:117db924cf7c | 2362 | wc_FreeRng(&rng); |
wolfSSL | 15:117db924cf7c | 2363 | return NULL; |
wolfSSL | 15:117db924cf7c | 2364 | } |
wolfSSL | 15:117db924cf7c | 2365 | XMEMCPY(mac->digest, digest, mac->digestSz); |
wolfSSL | 15:117db924cf7c | 2366 | } |
wolfSSL | 15:117db924cf7c | 2367 | else { |
wolfSSL | 15:117db924cf7c | 2368 | pkcs12->signData = NULL; |
wolfSSL | 15:117db924cf7c | 2369 | } |
wolfSSL | 15:117db924cf7c | 2370 | |
wolfSSL | 15:117db924cf7c | 2371 | wc_FreeRng(&rng); |
wolfSSL | 15:117db924cf7c | 2372 | (void)name; |
wolfSSL | 15:117db924cf7c | 2373 | (void)keyType; |
wolfSSL | 15:117db924cf7c | 2374 | |
wolfSSL | 15:117db924cf7c | 2375 | return pkcs12; |
wolfSSL | 15:117db924cf7c | 2376 | } |
wolfSSL | 15:117db924cf7c | 2377 | |
wolfSSL | 15:117db924cf7c | 2378 | |
wolfSSL | 15:117db924cf7c | 2379 | /* if using a specific memory heap */ |
wolfSSL | 15:117db924cf7c | 2380 | int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap) |
wolfSSL | 15:117db924cf7c | 2381 | { |
wolfSSL | 15:117db924cf7c | 2382 | if (pkcs12 == NULL) { |
wolfSSL | 15:117db924cf7c | 2383 | return BAD_FUNC_ARG; |
wolfSSL | 15:117db924cf7c | 2384 | } |
wolfSSL | 15:117db924cf7c | 2385 | pkcs12->heap = heap; |
wolfSSL | 15:117db924cf7c | 2386 | |
wolfSSL | 15:117db924cf7c | 2387 | return 0; |
wolfSSL | 15:117db924cf7c | 2388 | } |
wolfSSL | 15:117db924cf7c | 2389 | |
wolfSSL | 15:117db924cf7c | 2390 | |
wolfSSL | 15:117db924cf7c | 2391 | /* getter for heap */ |
wolfSSL | 15:117db924cf7c | 2392 | void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12) |
wolfSSL | 15:117db924cf7c | 2393 | { |
wolfSSL | 15:117db924cf7c | 2394 | if (pkcs12 == NULL) { |
wolfSSL | 15:117db924cf7c | 2395 | return NULL; |
wolfSSL | 15:117db924cf7c | 2396 | } |
wolfSSL | 15:117db924cf7c | 2397 | |
wolfSSL | 15:117db924cf7c | 2398 | return pkcs12->heap; |
wolfSSL | 15:117db924cf7c | 2399 | } |
wolfSSL | 15:117db924cf7c | 2400 | |
wolfSSL | 15:117db924cf7c | 2401 | #undef ERROR_OUT |
wolfSSL | 15:117db924cf7c | 2402 | |
wolfSSL | 16:8e0d178b1d1e | 2403 | #endif /* !NO_ASN && !NO_PWDBASED && HAVE_PKCS12 */ |
wolfSSL | 15:117db924cf7c | 2404 |