1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-12 01:53:07 +03:00

fixed pkcs12 mac issue

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@40 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich
2006-11-27 02:41:54 +00:00
parent 73c11ecadb
commit c98ded2eca
5 changed files with 131 additions and 95 deletions

132
ssl/p12.c
View File

@ -57,9 +57,14 @@
#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 int p8_decrypt(const char *password, const uint8_t *salt, int iter,
uint8_t *priv_key, int priv_key_len);
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(SSLCTX *ssl_ctx, uint8_t *priv_key);
static int get_pbe_params(uint8_t *buf, int *offset,
const uint8_t **salt, int *iterations);
@ -76,6 +81,8 @@ int pkcs8_decode(SSLCTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
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)
{
@ -100,11 +107,13 @@ int pkcs8_decode(SSLCTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
priv_key = &buf[offset];
p8_decrypt(password, salt, iterations, priv_key, len);
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;
}
@ -132,20 +141,12 @@ error:
}
/*
* Decrypt a pkcs8 block.
* Create the unicode password
*/
static int p8_decrypt(const char *password, const uint8_t *salt, int iter,
uint8_t *priv_key, int priv_key_len)
static char *make_uni_pass(const char *password, int *uni_pass_len)
{
uint8_t p[BLOCK_SIZE*2];
uint8_t d[BLOCK_SIZE];
uint8_t Ai[SHA1_SIZE];
SHA1_CTX sha_ctx;
RC4_CTX rc4_ctx;
uint8_t *uni_pass = NULL;
int i;
int uni_pass_len = 0;
int id = 1; /* key id */
int pass_len = 0, i;
char *uni_pass;
if (password == NULL)
{
@ -157,12 +158,29 @@ static int p8_decrypt(const char *password, const uint8_t *salt, int iter,
/* modify the password into a unicode version */
for (i = 0; i < (int)strlen(password); i++)
{
uni_pass[uni_pass_len++] = 0;
uni_pass[uni_pass_len++] = password[i];
uni_pass[pass_len++] = 0;
uni_pass[pass_len++] = password[i];
}
uni_pass[uni_pass_len++] = 0; /* null terminate */
uni_pass[uni_pass_len++] = 0;
uni_pass[pass_len++] = 0; /* null terminate */
uni_pass[pass_len++] = 0;
*uni_pass_len = pass_len;
return uni_pass;
}
/*
* Decrypt a pkcs8 block.
*/
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++)
{
@ -185,9 +203,14 @@ static int p8_decrypt(const char *password, const uint8_t *salt, int iter,
}
/* do the decryption */
RC4_setup(&rc4_ctx, Ai, 16);
RC4_crypt(&rc4_ctx, priv_key, priv_key, priv_key_len);
free(uni_pass);
if (id == PKCS12_KEY_ID)
{
RC4_setup(&rc4_ctx, Ai, 16);
RC4_crypt(&rc4_ctx, priv_key, priv_key, priv_key_len);
}
else /* MAC */
memcpy(priv_key, Ai, SHA1_SIZE);
return 0;
}
@ -198,13 +221,16 @@ static int p8_decrypt(const char *password, const uint8_t *salt, int iter,
int pkcs12_decode(SSLCTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
{
uint8_t *buf = ssl_obj->buf;
int all_ok = 0, len, iterations, key_offset, offset = 0;
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, *cert, *mac;
SHA1_CTX sha_ctx;
char sha[SHA1_SIZE];
uint8_t *version = NULL, *auth_safes = NULL, *cert, *orig_mac;
char key[SHA1_SIZE];
char mac[SHA1_SIZE];
const uint8_t *salt;
int ret;
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[] = /* pkc7 data */
{ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 };
static const uint8_t pkcs_encrypted[] = /* pkc7 encrypted */
@ -221,14 +247,10 @@ int pkcs12_decode(SSLCTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
}
if (asn1_get_int(buf, &offset, &version) < 0 || *version != 3)
{
error_code = SSL_ERROR_INVALID_VERSION;
goto error;
/* work out the MAC of this bit */
key_offset = offset;
asn1_skip_obj(buf, &key_offset, ASN1_SEQUENCE);
SHA1Init(&sha_ctx);
SHA1Update(&sha_ctx, &buf[offset], key_offset-offset);
SHA1Final(&sha_ctx, sha);
}
/* remove all the boring pcks7 bits */
if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
@ -240,8 +262,18 @@ int pkcs12_decode(SSLCTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
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_OCTET_STRING) < 0)
goto error;
/* work out the MAC start/end points (done on AuthSafes) */
auth_safes_start = offset;
auth_safes_end = offset;
asn1_skip_obj(buf, &auth_safes_end, ASN1_SEQUENCE);
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) ||
@ -268,7 +300,8 @@ int pkcs12_decode(SSLCTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
/* decrypt the certificate */
cert = &buf[offset];
if ((ret = p8_decrypt(password, salt, iterations, cert, len)) < 0)
if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert,
len, PKCS12_KEY_ID)) < 0)
goto error;
offset += len;
@ -327,7 +360,8 @@ int pkcs12_decode(SSLCTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
/* decrypt the private key */
cert = &buf[offset];
if ((ret = p8_decrypt(password, salt, iterations, cert, len)) < 0)
if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert,
len, PKCS12_KEY_ID)) < 0)
goto error;
offset += len;
@ -348,28 +382,34 @@ int pkcs12_decode(SSLCTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
len != SHA1_SIZE)
goto error;
mac = &buf[offset];
orig_mac = &buf[offset];
offset += len;
/* get the salt */
if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 ||
len != 8)
if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 || len != 8)
goto error;
salt = &buf[offset];
/* work out what the mac should be */
if ((ret = p8_decrypt(password, salt, iterations, mac, SHA1_SIZE)) < 0)
if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations,
key, SHA1_SIZE, PKCS12_MAC_ID)) < 0)
goto error;
/* TODO: actually memcmp the MAC - there is something wrong at the moment */
/* print_blob("MAC orig", sha, SHA1_SIZE); */
/* print_blob("MAC calc", mac, SHA1_SIZE); */
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);
return all_ok ? SSL_OK : SSL_ERROR_NOT_SUPPORTED;
free(uni_pass);
free(auth_safes);
return all_ok ? SSL_OK : error_code;
}
/*