This is a fork of the mbed port of axTLS

Dependents:   TLS_axTLS-Example HTTPSClientExample

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers p12.c Source File

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
00484 
00485