Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os by
p12.c
00001 /* 00002 * Copyright (c) 2007, Cameron Rich 00003 * 00004 * All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions are met: 00008 * 00009 * * Redistributions of source code must retain the above copyright notice, 00010 * this list of conditions and the following disclaimer. 00011 * * Redistributions in binary form must reproduce the above copyright notice, 00012 * this list of conditions and the following disclaimer in the documentation 00013 * and/or other materials provided with the distribution. 00014 * * Neither the name of the axTLS project nor the names of its contributors 00015 * may be used to endorse or promote products derived from this software 00016 * without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00019 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00021 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 00022 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00023 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00024 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00025 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00026 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00027 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 */ 00030 00031 /** 00032 * Process PKCS#8/PKCS#12 keys. 00033 * 00034 * The decoding of a PKCS#12 key is fairly specific - this code was tested on a 00035 * key generated with: 00036 * 00037 * openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem 00038 * -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 00039 * -name "p12_withoutCA" -out axTLS.withoutCA.p12 -password pass:abcd 00040 * 00041 * or with a certificate chain: 00042 * 00043 * openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem 00044 * -certfile axTLS.ca_x509.pem -keypbe PBE-SHA1-RC4-128 -certpbe 00045 * PBE-SHA1-RC4-128 -name "p12_withCA" -out axTLS.withCA.p12 -password pass:abcd 00046 * 00047 * Note that the PBE has to be specified with PBE-SHA1-RC4-128. The 00048 * private/public keys/certs have to use RSA encryption. Both the integrity 00049 * and privacy passwords are the same. 00050 * 00051 * The PKCS#8 files were generated with something like: 00052 * 00053 * PEM format: 00054 * openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -v1 00055 * PBE-SHA1-RC4-128 -out axTLS.encrypted_pem.p8 00056 * 00057 * DER format: 00058 * openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -outform DER 00059 * -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted.p8 00060 */ 00061 00062 #include <stdlib.h> 00063 #include <string.h> 00064 #include <stdio.h> 00065 #include "os_port.h" 00066 #include "ssl.h" 00067 00068 /* all commented out if not used */ 00069 #ifdef CONFIG_SSL_USE_PKCS12 00070 00071 #define BLOCK_SIZE 64 00072 #define PKCS12_KEY_ID 1 00073 #define PKCS12_IV_ID 2 00074 #define PKCS12_MAC_ID 3 00075 00076 static char *make_uni_pass(const char *password, int *uni_pass_len); 00077 static int p8_decrypt(const char *uni_pass, int uni_pass_len, 00078 const uint8_t *salt, int iter, 00079 uint8_t *priv_key, int priv_key_len, int id); 00080 static int p8_add_key(SSL_CTX *ssl_ctx, uint8_t *priv_key); 00081 static int get_pbe_params(uint8_t *buf, int *offset, 00082 const uint8_t **salt, int *iterations); 00083 00084 /* 00085 * Take a raw pkcs8 block and then decrypt it and turn it into a normal key. 00086 */ 00087 int pkcs8_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password) 00088 { 00089 uint8_t *buf = ssl_obj->buf; 00090 int len, offset = 0; 00091 int iterations; 00092 int ret = SSL_NOT_OK; 00093 uint8_t *version = NULL; 00094 const uint8_t *salt; 00095 uint8_t *priv_key; 00096 int uni_pass_len; 00097 char *uni_pass = make_uni_pass(password, &uni_pass_len); 00098 00099 if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0) 00100 { 00101 #ifdef CONFIG_SSL_FULL_MODE 00102 printf("Error: Invalid p8 ASN.1 file\n"); 00103 #endif 00104 goto error; 00105 } 00106 00107 /* unencrypted key? */ 00108 if (asn1_get_int(buf, &offset, &version) > 0 && *version == 0) 00109 { 00110 ret = p8_add_key(ssl_ctx, buf); 00111 goto error; 00112 } 00113 00114 if (get_pbe_params(buf, &offset, &salt, &iterations) < 0) 00115 goto error; 00116 00117 if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0) 00118 goto error; 00119 00120 priv_key = &buf[offset]; 00121 00122 p8_decrypt(uni_pass, uni_pass_len, salt, 00123 iterations, priv_key, len, PKCS12_KEY_ID); 00124 ret = p8_add_key(ssl_ctx, priv_key); 00125 00126 error: 00127 free(version); 00128 free(uni_pass); 00129 return ret; 00130 } 00131 00132 /* 00133 * Take the unencrypted pkcs8 and turn it into a private key 00134 */ 00135 static int p8_add_key(SSL_CTX *ssl_ctx, uint8_t *priv_key) 00136 { 00137 uint8_t *buf = priv_key; 00138 int len, offset = 0; 00139 int ret = SSL_NOT_OK; 00140 00141 /* Skip the preamble and go straight to the private key. 00142 We only support rsaEncryption (1.2.840.113549.1.1.1) */ 00143 if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00144 asn1_skip_obj(buf, &offset, ASN1_INTEGER) < 0 || 00145 asn1_skip_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00146 (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0) 00147 goto error; 00148 00149 ret = asn1_get_private_key(&buf[offset], len, &ssl_ctx->rsa_ctx); 00150 00151 error: 00152 return ret; 00153 } 00154 00155 /* 00156 * Create the unicode password 00157 */ 00158 static char *make_uni_pass(const char *password, int *uni_pass_len) 00159 { 00160 int pass_len = 0, i; 00161 char *uni_pass; 00162 00163 if (password == NULL) 00164 { 00165 password = ""; 00166 } 00167 00168 uni_pass = (char *)malloc((strlen(password)+1)*2); 00169 00170 /* modify the password into a unicode version */ 00171 for (i = 0; i < (int)strlen(password); i++) 00172 { 00173 uni_pass[pass_len++] = 0; 00174 uni_pass[pass_len++] = password[i]; 00175 } 00176 00177 uni_pass[pass_len++] = 0; /* null terminate */ 00178 uni_pass[pass_len++] = 0; 00179 *uni_pass_len = pass_len; 00180 return uni_pass; 00181 } 00182 00183 /* 00184 * Decrypt a pkcs8 block. 00185 */ 00186 static int p8_decrypt(const char *uni_pass, int uni_pass_len, 00187 const uint8_t *salt, int iter, 00188 uint8_t *priv_key, int priv_key_len, int id) 00189 { 00190 uint8_t p[BLOCK_SIZE*2]; 00191 uint8_t d[BLOCK_SIZE]; 00192 uint8_t Ai[SHA1_SIZE]; 00193 SHA1_CTX sha_ctx; 00194 RC4_CTX rc4_ctx; 00195 int i; 00196 00197 for (i = 0; i < BLOCK_SIZE; i++) 00198 { 00199 p[i] = salt[i % SALT_SIZE]; 00200 p[BLOCK_SIZE+i] = uni_pass[i % uni_pass_len]; 00201 d[i] = id; 00202 } 00203 00204 /* get the key - no IV since we are using RC4 */ 00205 SHA1_Init(&sha_ctx); 00206 SHA1_Update(&sha_ctx, d, sizeof(d)); 00207 SHA1_Update(&sha_ctx, p, sizeof(p)); 00208 SHA1_Final(Ai, &sha_ctx); 00209 00210 for (i = 1; i < iter; i++) 00211 { 00212 SHA1_Init(&sha_ctx); 00213 SHA1_Update(&sha_ctx, Ai, SHA1_SIZE); 00214 SHA1_Final(Ai, &sha_ctx); 00215 } 00216 00217 /* do the decryption */ 00218 if (id == PKCS12_KEY_ID) 00219 { 00220 RC4_setup(&rc4_ctx, Ai, 16); 00221 RC4_crypt(&rc4_ctx, priv_key, priv_key, priv_key_len); 00222 } 00223 else /* MAC */ 00224 memcpy(priv_key, Ai, SHA1_SIZE); 00225 00226 return 0; 00227 } 00228 00229 /* 00230 * Take a raw pkcs12 block and the decrypt it and turn it into a certificate(s) 00231 * and keys. 00232 */ 00233 int pkcs12_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password) 00234 { 00235 uint8_t *buf = ssl_obj->buf; 00236 int len, iterations, auth_safes_start, 00237 auth_safes_end, auth_safes_len, key_offset, offset = 0; 00238 int all_certs = 0; 00239 uint8_t *version = NULL, *auth_safes = NULL, *cert, *orig_mac; 00240 uint8_t key[SHA1_SIZE]; 00241 uint8_t mac[SHA1_SIZE]; 00242 const uint8_t *salt; 00243 int uni_pass_len, ret = SSL_OK; 00244 char *uni_pass = make_uni_pass(password, &uni_pass_len); 00245 static const uint8_t pkcs_data[] = /* pkc7 data */ 00246 { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 }; 00247 static const uint8_t pkcs_encrypted[] = /* pkc7 encrypted */ 00248 { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06 }; 00249 static const uint8_t pkcs8_key_bag[] = /* 1.2.840.113549.1.12.10.1.2 */ 00250 { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02 }; 00251 00252 if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0) 00253 { 00254 #ifdef CONFIG_SSL_FULL_MODE 00255 printf("Error: Invalid p12 ASN.1 file\n"); 00256 #endif 00257 goto error; 00258 } 00259 00260 if (asn1_get_int(buf, &offset, &version) < 0 || *version != 3) 00261 { 00262 ret = SSL_ERROR_INVALID_VERSION; 00263 goto error; 00264 } 00265 00266 /* remove all the boring pcks7 bits */ 00267 if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00268 (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 || 00269 len != sizeof(pkcs_data) || 00270 memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data))) 00271 goto error; 00272 00273 offset += len; 00274 00275 if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 || 00276 asn1_next_obj(buf, &offset, ASN1_OCTET_STRING) < 0) 00277 goto error; 00278 00279 /* work out the MAC start/end points (done on AuthSafes) */ 00280 auth_safes_start = offset; 00281 auth_safes_end = offset; 00282 if (asn1_skip_obj(buf, &auth_safes_end, ASN1_SEQUENCE) < 0) 00283 goto error; 00284 00285 auth_safes_len = auth_safes_end - auth_safes_start; 00286 auth_safes = malloc(auth_safes_len); 00287 00288 memcpy(auth_safes, &buf[auth_safes_start], auth_safes_len); 00289 00290 if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00291 asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00292 (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 || 00293 (len != sizeof(pkcs_encrypted) || 00294 memcmp(&buf[offset], pkcs_encrypted, sizeof(pkcs_encrypted)))) 00295 goto error; 00296 00297 offset += len; 00298 00299 if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 || 00300 asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00301 asn1_skip_obj(buf, &offset, ASN1_INTEGER) < 0 || 00302 asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00303 (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 || 00304 len != sizeof(pkcs_data) || 00305 memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data))) 00306 goto error; 00307 00308 offset += len; 00309 00310 /* work out the salt for the certificate */ 00311 if (get_pbe_params(buf, &offset, &salt, &iterations) < 0 || 00312 (len = asn1_next_obj(buf, &offset, ASN1_IMPLICIT_TAG)) < 0) 00313 goto error; 00314 00315 /* decrypt the certificate */ 00316 cert = &buf[offset]; 00317 if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert, 00318 len, PKCS12_KEY_ID)) < 0) 00319 goto error; 00320 00321 offset += len; 00322 00323 /* load the certificate */ 00324 key_offset = 0; 00325 all_certs = asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE); 00326 00327 /* keep going until all certs are loaded */ 00328 while (key_offset < all_certs) 00329 { 00330 int cert_offset = key_offset; 00331 00332 if (asn1_skip_obj(cert, &cert_offset, ASN1_SEQUENCE) < 0 || 00333 asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE) < 0 || 00334 asn1_skip_obj(cert, &key_offset, ASN1_OID) < 0 || 00335 asn1_next_obj(cert, &key_offset, ASN1_EXPLICIT_TAG) < 0 || 00336 asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE) < 0 || 00337 asn1_skip_obj(cert, &key_offset, ASN1_OID) < 0 || 00338 asn1_next_obj(cert, &key_offset, ASN1_EXPLICIT_TAG) < 0 || 00339 (len = asn1_next_obj(cert, &key_offset, ASN1_OCTET_STRING)) < 0) 00340 goto error; 00341 00342 if ((ret = add_cert(ssl_ctx, &cert[key_offset], len)) < 0) 00343 goto error; 00344 00345 key_offset = cert_offset; 00346 } 00347 00348 if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00349 (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 || 00350 len != sizeof(pkcs_data) || 00351 memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data))) 00352 goto error; 00353 00354 offset += len; 00355 00356 if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 || 00357 asn1_next_obj(buf, &offset, ASN1_OCTET_STRING) < 0 || 00358 asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00359 asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00360 (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 || 00361 (len != sizeof(pkcs8_key_bag)) || 00362 memcmp(&buf[offset], pkcs8_key_bag, sizeof(pkcs8_key_bag))) 00363 goto error; 00364 00365 offset += len; 00366 00367 /* work out the salt for the private key */ 00368 if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 || 00369 asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00370 get_pbe_params(buf, &offset, &salt, &iterations) < 0 || 00371 (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0) 00372 goto error; 00373 00374 /* decrypt the private key */ 00375 cert = &buf[offset]; 00376 if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert, 00377 len, PKCS12_KEY_ID)) < 0) 00378 goto error; 00379 00380 offset += len; 00381 00382 /* load the private key */ 00383 if ((ret = p8_add_key(ssl_ctx, cert)) < 0) 00384 goto error; 00385 00386 /* miss out on friendly name, local key id etc */ 00387 if (asn1_skip_obj(buf, &offset, ASN1_SET) < 0) 00388 goto error; 00389 00390 /* work out the MAC */ 00391 if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00392 asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00393 asn1_skip_obj(buf, &offset, ASN1_SEQUENCE) < 0 || 00394 (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 || 00395 len != SHA1_SIZE) 00396 goto error; 00397 00398 orig_mac = &buf[offset]; 00399 offset += len; 00400 00401 /* get the salt */ 00402 if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 || len != 8) 00403 goto error; 00404 00405 salt = &buf[offset]; 00406 00407 /* work out what the mac should be */ 00408 if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, 00409 key, SHA1_SIZE, PKCS12_MAC_ID)) < 0) 00410 goto error; 00411 00412 hmac_sha1(auth_safes, auth_safes_len, key, SHA1_SIZE, mac); 00413 00414 if (memcmp(mac, orig_mac, SHA1_SIZE)) 00415 { 00416 ret = SSL_ERROR_INVALID_HMAC; 00417 goto error; 00418 } 00419 00420 error: 00421 free(version); 00422 free(uni_pass); 00423 free(auth_safes); 00424 return ret; 00425 } 00426 00427 /* 00428 * Retrieve the salt/iteration details from a PBE block. 00429 */ 00430 static int get_pbe_params(uint8_t *buf, int *offset, 00431 const uint8_t **salt, int *iterations) 00432 { 00433 static const uint8_t pbeSH1RC4[] = /* pbeWithSHAAnd128BitRC4 */ 00434 { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x01 }; 00435 00436 int i, len; 00437 uint8_t *iter = NULL; 00438 int error_code = SSL_ERROR_NOT_SUPPORTED; 00439 00440 /* Get the PBE type */ 00441 if (asn1_next_obj(buf, offset, ASN1_SEQUENCE) < 0 || 00442 (len = asn1_next_obj(buf, offset, ASN1_OID)) < 0) 00443 goto error; 00444 00445 /* we expect pbeWithSHAAnd128BitRC4 (1.2.840.113549.1.12.1.1) 00446 which is the only algorithm we support */ 00447 if (len != sizeof(pbeSH1RC4) || 00448 memcmp(&buf[*offset], pbeSH1RC4, sizeof(pbeSH1RC4))) 00449 { 00450 #ifdef CONFIG_SSL_FULL_MODE 00451 printf("Error: pkcs8/pkcs12 must use \"PBE-SHA1-RC4-128\"\n"); 00452 #endif 00453 goto error; 00454 } 00455 00456 *offset += len; 00457 00458 if (asn1_next_obj(buf, offset, ASN1_SEQUENCE) < 0 || 00459 (len = asn1_next_obj(buf, offset, ASN1_OCTET_STRING)) < 0 || 00460 len != 8) 00461 goto error; 00462 00463 *salt = &buf[*offset]; 00464 *offset += len; 00465 00466 if ((len = asn1_get_int(buf, offset, &iter)) < 0) 00467 goto error; 00468 00469 *iterations = 0; 00470 for (i = 0; i < len; i++) 00471 { 00472 (*iterations) <<= 8; 00473 (*iterations) += iter[i]; 00474 } 00475 00476 free(iter); 00477 error_code = SSL_OK; /* got here - we are ok */ 00478 00479 error: 00480 return error_code; 00481 } 00482 00483 #endif
Generated on Tue Jul 12 2022 13:16:03 by
