123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include "ssl.h"
- #ifdef CONFIG_SSL_USE_PKCS12
- #define BLOCK_SIZE 64
- #define PKCS12_KEY_ID 1
- #define PKCS12_IV_ID 2
- #define PKCS12_MAC_ID 3
- static char *make_uni_pass(const char *password, int *uni_pass_len);
- static int p8_decrypt(const char *uni_pass, int uni_pass_len,
- const uint8_t *salt, int iter,
- uint8_t *priv_key, int priv_key_len, int id);
- static int p8_add_key(SSL_CTX *ssl_ctx, uint8_t *priv_key);
- static int get_pbe_params(uint8_t *buf, int *offset,
- const uint8_t **salt, int *iterations);
- int pkcs8_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
- {
- uint8_t *buf = ssl_obj->buf;
- int len, offset = 0;
- int iterations;
- int ret = SSL_NOT_OK;
- uint8_t *version = NULL;
- const uint8_t *salt;
- uint8_t *priv_key;
- int uni_pass_len;
- char *uni_pass = make_uni_pass(password, &uni_pass_len);
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0)
- {
- #ifdef CONFIG_SSL_FULL_MODE
- printf("Error: Invalid p8 ASN.1 file\n");
- #endif
- goto error;
- }
-
- if (asn1_get_int(buf, &offset, &version) > 0 && *version == 0)
- {
- ret = p8_add_key(ssl_ctx, buf);
- goto error;
- }
- if (get_pbe_params(buf, &offset, &salt, &iterations) < 0)
- goto error;
- if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
- goto error;
- priv_key = &buf[offset];
- p8_decrypt(uni_pass, uni_pass_len, salt,
- iterations, priv_key, len, PKCS12_KEY_ID);
- ret = p8_add_key(ssl_ctx, priv_key);
- error:
- free(version);
- free(uni_pass);
- return ret;
- }
- static int p8_add_key(SSL_CTX *ssl_ctx, uint8_t *priv_key)
- {
- uint8_t *buf = priv_key;
- int len, offset = 0;
- int ret = SSL_NOT_OK;
-
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(buf, &offset, ASN1_INTEGER) < 0 ||
- asn1_skip_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
- goto error;
- ret = asn1_get_private_key(&buf[offset], len, &ssl_ctx->rsa_ctx);
- error:
- return ret;
- }
- static char *make_uni_pass(const char *password, int *uni_pass_len)
- {
- int pass_len = 0, i;
- char *uni_pass;
- if (password == NULL)
- {
- password = "";
- }
- uni_pass = (char *)malloc((strlen(password)+1)*2);
-
- for (i = 0; i < (int)strlen(password); i++)
- {
- uni_pass[pass_len++] = 0;
- uni_pass[pass_len++] = password[i];
- }
- uni_pass[pass_len++] = 0;
- uni_pass[pass_len++] = 0;
- *uni_pass_len = pass_len;
- return uni_pass;
- }
- static int p8_decrypt(const char *uni_pass, int uni_pass_len,
- const uint8_t *salt, int iter,
- uint8_t *priv_key, int priv_key_len, int id)
- {
- uint8_t p[BLOCK_SIZE*2];
- uint8_t d[BLOCK_SIZE];
- uint8_t Ai[SHA1_SIZE];
- SHA1_CTX sha_ctx;
- RC4_CTX rc4_ctx;
- int i;
- for (i = 0; i < BLOCK_SIZE; i++)
- {
- p[i] = salt[i % SALT_SIZE];
- p[BLOCK_SIZE+i] = uni_pass[i % uni_pass_len];
- d[i] = id;
- }
-
- SHA1_Init(&sha_ctx);
- SHA1_Update(&sha_ctx, d, sizeof(d));
- SHA1_Update(&sha_ctx, p, sizeof(p));
- SHA1_Final(Ai, &sha_ctx);
- for (i = 1; i < iter; i++)
- {
- SHA1_Init(&sha_ctx);
- SHA1_Update(&sha_ctx, Ai, SHA1_SIZE);
- SHA1_Final(Ai, &sha_ctx);
- }
-
- if (id == PKCS12_KEY_ID)
- {
- RC4_setup(&rc4_ctx, Ai, 16);
- RC4_crypt(&rc4_ctx, priv_key, priv_key, priv_key_len);
- }
- else
- memcpy(priv_key, Ai, SHA1_SIZE);
- return 0;
- }
- int pkcs12_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
- {
- uint8_t *buf = ssl_obj->buf;
- int all_ok = 0, len, iterations, auth_safes_start,
- auth_safes_end, auth_safes_len, key_offset, offset = 0;
- int all_certs = 0;
- uint8_t *version = NULL, *auth_safes = NULL, *cert, *orig_mac;
- uint8_t key[SHA1_SIZE];
- uint8_t mac[SHA1_SIZE];
- const uint8_t *salt;
- int uni_pass_len, ret;
- int error_code = SSL_ERROR_NOT_SUPPORTED;
- char *uni_pass = make_uni_pass(password, &uni_pass_len);
- static const uint8_t pkcs_data[] =
- { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 };
- static const uint8_t pkcs_encrypted[] =
- { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06 };
- static const uint8_t pkcs8_key_bag[] =
- { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02 };
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0)
- {
- #ifdef CONFIG_SSL_FULL_MODE
- printf("Error: Invalid p12 ASN.1 file\n");
- #endif
- goto error;
- }
- if (asn1_get_int(buf, &offset, &version) < 0 || *version != 3)
- {
- error_code = SSL_ERROR_INVALID_VERSION;
- goto error;
- }
-
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
- len != sizeof(pkcs_data) ||
- memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
- goto error;
- offset += len;
- if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_OCTET_STRING) < 0)
- goto error;
-
- auth_safes_start = offset;
- auth_safes_end = offset;
- if (asn1_skip_obj(buf, &auth_safes_end, ASN1_SEQUENCE) < 0)
- goto error;
- auth_safes_len = auth_safes_end - auth_safes_start;
- auth_safes = malloc(auth_safes_len);
- memcpy(auth_safes, &buf[auth_safes_start], auth_safes_len);
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
- (len != sizeof(pkcs_encrypted) ||
- memcmp(&buf[offset], pkcs_encrypted, sizeof(pkcs_encrypted))))
- goto error;
- offset += len;
- if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(buf, &offset, ASN1_INTEGER) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
- len != sizeof(pkcs_data) ||
- memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
- goto error;
- offset += len;
-
- if (get_pbe_params(buf, &offset, &salt, &iterations) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_IMPLICIT_TAG)) < 0)
- goto error;
-
- cert = &buf[offset];
- if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert,
- len, PKCS12_KEY_ID)) < 0)
- goto error;
- offset += len;
-
- key_offset = 0;
- all_certs = asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE);
-
- while (key_offset < all_certs)
- {
- int cert_offset = key_offset;
- if (asn1_skip_obj(cert, &cert_offset, ASN1_SEQUENCE) < 0 ||
- asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(cert, &key_offset, ASN1_OID) < 0 ||
- asn1_next_obj(cert, &key_offset, ASN1_EXPLICIT_TAG) < 0 ||
- asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(cert, &key_offset, ASN1_OID) < 0 ||
- asn1_next_obj(cert, &key_offset, ASN1_EXPLICIT_TAG) < 0 ||
- (len = asn1_next_obj(cert, &key_offset, ASN1_OCTET_STRING)) < 0)
- goto error;
- if ((ret = add_cert(ssl_ctx, &cert[key_offset], len)) < 0)
- goto error;
- key_offset = cert_offset;
- }
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
- len != sizeof(pkcs_data) ||
- memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
- goto error;
- offset += len;
- if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_OCTET_STRING) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
- (len != sizeof(pkcs8_key_bag)) ||
- memcmp(&buf[offset], pkcs8_key_bag, sizeof(pkcs8_key_bag)))
- goto error;
- offset += len;
-
- if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- get_pbe_params(buf, &offset, &salt, &iterations) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
- goto error;
-
- cert = &buf[offset];
- if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert,
- len, PKCS12_KEY_ID)) < 0)
- goto error;
- offset += len;
-
- if ((ret = p8_add_key(ssl_ctx, cert)) < 0)
- goto error;
-
- if (asn1_skip_obj(buf, &offset, ASN1_SET) < 0)
- goto error;
-
- if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- asn1_skip_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 ||
- len != SHA1_SIZE)
- goto error;
- orig_mac = &buf[offset];
- offset += len;
-
- if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 || len != 8)
- goto error;
- salt = &buf[offset];
-
- if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations,
- key, SHA1_SIZE, PKCS12_MAC_ID)) < 0)
- goto error;
- hmac_sha1(auth_safes, auth_safes_len, key, SHA1_SIZE, mac);
- if (memcmp(mac, orig_mac, SHA1_SIZE))
- {
- error_code = SSL_ERROR_INVALID_HMAC;
- goto error;
- }
- all_ok = 1;
- error:
- free(version);
- free(uni_pass);
- free(auth_safes);
- return all_ok ? SSL_OK : error_code;
- }
- static int get_pbe_params(uint8_t *buf, int *offset,
- const uint8_t **salt, int *iterations)
- {
- static const uint8_t pbeSH1RC4[] =
- { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x01 };
- int i, len;
- uint8_t *iter = NULL;
- int error_code = SSL_ERROR_NOT_SUPPORTED;
-
- if (asn1_next_obj(buf, offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
- goto error;
-
- if (len != sizeof(pbeSH1RC4) ||
- memcmp(&buf[*offset], pbeSH1RC4, sizeof(pbeSH1RC4)))
- {
- #ifdef CONFIG_SSL_FULL_MODE
- printf("Error: pkcs8/pkcs12 must use \"PBE-SHA1-RC4-128\"\n");
- #endif
- goto error;
- }
- *offset += len;
- if (asn1_next_obj(buf, offset, ASN1_SEQUENCE) < 0 ||
- (len = asn1_next_obj(buf, offset, ASN1_OCTET_STRING)) < 0 ||
- len != 8)
- goto error;
- *salt = &buf[*offset];
- *offset += len;
- if ((len = asn1_get_int(buf, offset, &iter)) < 0)
- goto error;
- *iterations = 0;
- for (i = 0; i < len; i++)
- {
- (*iterations) <<= 8;
- (*iterations) += iter[i];
- }
- free(iter);
- error_code = SSL_OK;
- error:
- return error_code;
- }
- #endif
|