/*
* Wrapper functions for OpenSSL libcrypto
- * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
#include "common.h"
#include "wpabuf.h"
#include "dh_group5.h"
+#include "sha1.h"
+#include "sha256.h"
+#include "sha384.h"
#include "crypto.h"
-#if OPENSSL_VERSION_NUMBER < 0x00907000
-#define DES_key_schedule des_key_schedule
-#define DES_cblock des_cblock
-#define DES_set_key(key, schedule) des_set_key((key), *(schedule))
-#define DES_ecb_encrypt(input, output, ks, enc) \
- des_ecb_encrypt((input), (output), *(ks), (enc))
-#endif /* openssl < 0.9.7 */
-
static BIGNUM * get_group5_prime(void)
{
-#if OPENSSL_VERSION_NUMBER < 0x00908000
+#ifdef OPENSSL_IS_BORINGSSL
static const unsigned char RFC3526_PRIME_1536[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL);
-#else /* openssl < 0.9.8 */
+#else /* OPENSSL_IS_BORINGSSL */
return get_rfc3526_prime_1536(NULL);
-#endif /* openssl < 0.9.8 */
+#endif /* OPENSSL_IS_BORINGSSL */
}
-#if OPENSSL_VERSION_NUMBER < 0x00908000
-#ifndef OPENSSL_NO_SHA256
-#ifndef OPENSSL_FIPS
-#define NO_SHA256_WRAPPER
-#endif
-#endif
-
-#endif /* openssl < 0.9.8 */
-
#ifdef OPENSSL_NO_SHA256
#define NO_SHA256_WRAPPER
#endif
}
pkey[i] = next | 1;
- DES_set_key(&pkey, &ks);
+ DES_set_key((DES_cblock *) &pkey, &ks);
DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks,
DES_ENCRYPT);
}
switch (keylen) {
case 16:
return EVP_aes_128_ecb();
+#ifndef OPENSSL_IS_BORINGSSL
case 24:
return EVP_aes_192_ecb();
+#endif /* OPENSSL_IS_BORINGSSL */
case 32:
return EVP_aes_256_ecb();
}
"in AES encrypt", len);
}
EVP_CIPHER_CTX_cleanup(c);
- os_free(c);
+ bin_clear_free(c, sizeof(*c));
}
"in AES decrypt", len);
}
EVP_CIPHER_CTX_cleanup(c);
- os_free(ctx);
+ bin_clear_free(c, sizeof(*c));
+}
+
+
+int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
+{
+ AES_KEY actx;
+ int res;
+
+ if (AES_set_encrypt_key(kek, kek_len << 3, &actx))
+ return -1;
+ res = AES_wrap_key(&actx, NULL, cipher, plain, n * 8);
+ OPENSSL_cleanse(&actx, sizeof(actx));
+ return res <= 0 ? -1 : 0;
+}
+
+
+int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
+ u8 *plain)
+{
+ AES_KEY actx;
+ int res;
+
+ if (AES_set_decrypt_key(kek, kek_len << 3, &actx))
+ return -1;
+ res = AES_unwrap_key(&actx, NULL, plain, cipher, (n + 1) * 8);
+ OPENSSL_cleanse(&actx, sizeof(actx));
+ return res <= 0 ? -1 : 0;
}
ret = 0;
error:
- BN_free(bn_base);
- BN_free(bn_exp);
- BN_free(bn_modulus);
- BN_free(bn_result);
+ BN_clear_free(bn_base);
+ BN_clear_free(bn_exp);
+ BN_clear_free(bn_modulus);
+ BN_clear_free(bn_result);
BN_CTX_free(ctx);
return ret;
}
case 16:
cipher = EVP_aes_128_cbc();
break;
+#ifndef OPENSSL_IS_BORINGSSL
case 24:
cipher = EVP_aes_192_cbc();
break;
+#endif /* OPENSSL_IS_BORINGSSL */
case 32:
cipher = EVP_aes_256_cbc();
break;
return dh;
err:
- wpabuf_free(pubkey);
- wpabuf_free(privkey);
+ wpabuf_clear_free(pubkey);
+ wpabuf_clear_free(privkey);
DH_free(dh);
return NULL;
}
if (keylen < 0)
goto err;
wpabuf_put(res, keylen);
- BN_free(pub_key);
+ BN_clear_free(pub_key);
return res;
err:
- BN_free(pub_key);
- wpabuf_free(res);
+ BN_clear_free(pub_key);
+ wpabuf_clear_free(res);
return NULL;
}
HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL);
#else /* openssl < 0.9.9 */
if (HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL) != 1) {
- os_free(ctx);
+ bin_clear_free(ctx, sizeof(*ctx));
return NULL;
}
#endif /* openssl < 0.9.9 */
return -2;
if (mac == NULL || len == NULL) {
- os_free(ctx);
+ bin_clear_free(ctx, sizeof(*ctx));
return 0;
}
res = HMAC_Final(&ctx->ctx, mac, &mdlen);
#endif /* openssl < 0.9.9 */
HMAC_CTX_cleanup(&ctx->ctx);
- os_free(ctx);
+ bin_clear_free(ctx, sizeof(*ctx));
if (res == 1) {
*len = mdlen;
}
-int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
- int iterations, u8 *buf, size_t buflen)
-{
-#if OPENSSL_VERSION_NUMBER < 0x00908000
- if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase),
- (unsigned char *) ssid,
- ssid_len, 4096, buflen, buf) != 1)
- return -1;
-#else /* openssl < 0.9.8 */
- if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase), ssid,
- ssid_len, 4096, buflen, buf) != 1)
- return -1;
-#endif /* openssl < 0.9.8 */
- return 0;
-}
-
-
-int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
- const u8 *addr[], const size_t *len, u8 *mac)
+static int openssl_hmac_vector(const EVP_MD *type, const u8 *key,
+ size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac,
+ unsigned int mdlen)
{
HMAC_CTX ctx;
size_t i;
- unsigned int mdlen;
int res;
HMAC_CTX_init(&ctx);
#if OPENSSL_VERSION_NUMBER < 0x00909000
- HMAC_Init_ex(&ctx, key, key_len, EVP_sha1(), NULL);
+ HMAC_Init_ex(&ctx, key, key_len, type, NULL);
#else /* openssl < 0.9.9 */
- if (HMAC_Init_ex(&ctx, key, key_len, EVP_sha1(), NULL) != 1)
+ if (HMAC_Init_ex(&ctx, key, key_len, type, NULL) != 1)
return -1;
#endif /* openssl < 0.9.9 */
for (i = 0; i < num_elem; i++)
HMAC_Update(&ctx, addr[i], len[i]);
- mdlen = 20;
#if OPENSSL_VERSION_NUMBER < 0x00909000
HMAC_Final(&ctx, mac, &mdlen);
res = 1;
}
+#ifndef CONFIG_FIPS
+
+int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
+{
+ return openssl_hmac_vector(EVP_md5(), key ,key_len, num_elem, addr, len,
+ mac, 16);
+}
+
+
+int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+ u8 *mac)
+{
+ return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
+}
+
+#endif /* CONFIG_FIPS */
+
+
+int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
+ int iterations, u8 *buf, size_t buflen)
+{
+ if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase), ssid,
+ ssid_len, iterations, buflen, buf) != 1)
+ return -1;
+ return 0;
+}
+
+
+int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
+{
+ return openssl_hmac_vector(EVP_sha1(), key, key_len, num_elem, addr,
+ len, mac, 20);
+}
+
+
int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
u8 *mac)
{
int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac)
{
- HMAC_CTX ctx;
- size_t i;
- unsigned int mdlen;
- int res;
+ return openssl_hmac_vector(EVP_sha256(), key, key_len, num_elem, addr,
+ len, mac, 32);
+}
- HMAC_CTX_init(&ctx);
-#if OPENSSL_VERSION_NUMBER < 0x00909000
- HMAC_Init_ex(&ctx, key, key_len, EVP_sha256(), NULL);
-#else /* openssl < 0.9.9 */
- if (HMAC_Init_ex(&ctx, key, key_len, EVP_sha256(), NULL) != 1)
- return -1;
-#endif /* openssl < 0.9.9 */
- for (i = 0; i < num_elem; i++)
- HMAC_Update(&ctx, addr[i], len[i]);
+int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
+ size_t data_len, u8 *mac)
+{
+ return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
+}
- mdlen = 32;
-#if OPENSSL_VERSION_NUMBER < 0x00909000
- HMAC_Final(&ctx, mac, &mdlen);
- res = 1;
-#else /* openssl < 0.9.9 */
- res = HMAC_Final(&ctx, mac, &mdlen);
-#endif /* openssl < 0.9.9 */
- HMAC_CTX_cleanup(&ctx);
+#endif /* CONFIG_SHA256 */
- return res == 1 ? 0 : -1;
+
+#ifdef CONFIG_SHA384
+
+int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
+{
+ return openssl_hmac_vector(EVP_sha384(), key, key_len, num_elem, addr,
+ len, mac, 32);
}
-int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
+int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac)
{
- return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
+ return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
}
-#endif /* CONFIG_SHA256 */
+#endif /* CONFIG_SHA384 */
int crypto_get_random(void *buf, size_t len)
#ifdef CONFIG_OPENSSL_CMAC
-int omac1_aes_128_vector(const u8 *key, size_t num_elem,
- const u8 *addr[], const size_t *len, u8 *mac)
+int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
{
CMAC_CTX *ctx;
int ret = -1;
if (ctx == NULL)
return -1;
- if (!CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL))
+ if (key_len == 32) {
+ if (!CMAC_Init(ctx, key, 32, EVP_aes_256_cbc(), NULL))
+ goto fail;
+ } else if (key_len == 16) {
+ if (!CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL))
+ goto fail;
+ } else {
goto fail;
+ }
for (i = 0; i < num_elem; i++) {
if (!CMAC_Update(ctx, addr[i], len[i]))
goto fail;
}
+int omac1_aes_128_vector(const u8 *key, size_t num_elem,
+ const u8 *addr[], const size_t *len, u8 *mac)
+{
+ return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
+}
+
+
int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
{
return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
}
+
+
+int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
+{
+ return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
+}
#endif /* CONFIG_OPENSSL_CMAC */
}
+int crypto_bignum_exptmod(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ const struct crypto_bignum *c,
+ struct crypto_bignum *d)
+{
+ int res;
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -1;
+ res = BN_mod_exp((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
+ (const BIGNUM *) c, bnctx);
+ BN_CTX_free(bnctx);
+
+ return res ? 0 : -1;
+}
+
+
+int crypto_bignum_inverse(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c)
+{
+ BIGNUM *res;
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -1;
+ res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a,
+ (const BIGNUM *) b, bnctx);
+ BN_CTX_free(bnctx);
+
+ return res ? 0 : -1;
+}
+
+
+int crypto_bignum_sub(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c)
+{
+ return BN_sub((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ?
+ 0 : -1;
+}
+
+
+int crypto_bignum_div(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ struct crypto_bignum *c)
+{
+ int res;
+
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -1;
+ res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a,
+ (const BIGNUM *) b, bnctx);
+ BN_CTX_free(bnctx);
+
+ return res ? 0 : -1;
+}
+
+
+int crypto_bignum_mulmod(const struct crypto_bignum *a,
+ const struct crypto_bignum *b,
+ const struct crypto_bignum *c,
+ struct crypto_bignum *d)
+{
+ int res;
+
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -1;
+ res = BN_mod_mul((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b,
+ (const BIGNUM *) c, bnctx);
+ BN_CTX_free(bnctx);
+
+ return res ? 0 : -1;
+}
+
+
+int crypto_bignum_cmp(const struct crypto_bignum *a,
+ const struct crypto_bignum *b)
+{
+ return BN_cmp((const BIGNUM *) a, (const BIGNUM *) b);
+}
+
+
+int crypto_bignum_bits(const struct crypto_bignum *a)
+{
+ return BN_num_bits((const BIGNUM *) a);
+}
+
+
+int crypto_bignum_is_zero(const struct crypto_bignum *a)
+{
+ return BN_is_zero((const BIGNUM *) a);
+}
+
+
+int crypto_bignum_is_one(const struct crypto_bignum *a)
+{
+ return BN_is_one((const BIGNUM *) a);
+}
+
+
#ifdef CONFIG_ECC
struct crypto_ec {
EC_GROUP *group;
BN_CTX *bnctx;
- size_t prime_len;
BIGNUM *prime;
BIGNUM *order;
};
struct crypto_ec * crypto_ec_init(int group)
{
struct crypto_ec *e;
+ int nid;
- if (group != 19)
+ /* Map from IANA registry for IKE D-H groups to OpenSSL NID */
+ switch (group) {
+ case 19:
+ nid = NID_X9_62_prime256v1;
+ break;
+ case 20:
+ nid = NID_secp384r1;
+ break;
+ case 21:
+ nid = NID_secp521r1;
+ break;
+ case 25:
+ nid = NID_X9_62_prime192v1;
+ break;
+ case 26:
+ nid = NID_secp224r1;
+ break;
+ default:
return NULL;
+ }
e = os_zalloc(sizeof(*e));
if (e == NULL)
return NULL;
- e->prime_len = 32;
e->bnctx = BN_CTX_new();
- e->group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
+ e->group = EC_GROUP_new_by_curve_name(nid);
e->prime = BN_new();
e->order = BN_new();
if (e->group == NULL || e->bnctx == NULL || e->prime == NULL ||
{
if (e == NULL)
return;
- BN_free(e->order);
+ BN_clear_free(e->order);
+ BN_clear_free(e->prime);
EC_GROUP_free(e->group);
BN_CTX_free(e->bnctx);
os_free(e);
size_t crypto_ec_prime_len(struct crypto_ec *e)
{
- return e->prime_len;
+ return BN_num_bytes(e->prime);
+}
+
+
+size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
+{
+ return BN_num_bits(e->prime);
}
{
BIGNUM *x_bn, *y_bn;
int ret = -1;
+ int len = BN_num_bytes(e->prime);
x_bn = BN_new();
y_bn = BN_new();
x_bn, y_bn, e->bnctx)) {
if (x) {
crypto_bignum_to_bin((struct crypto_bignum *) x_bn,
- x, e->prime_len, e->prime_len);
+ x, len, len);
}
if (y) {
crypto_bignum_to_bin((struct crypto_bignum *) y_bn,
- y, e->prime_len, e->prime_len);
+ y, len, len);
}
ret = 0;
}
- BN_free(x_bn);
- BN_free(y_bn);
+ BN_clear_free(x_bn);
+ BN_clear_free(y_bn);
return ret;
}
{
BIGNUM *x, *y;
EC_POINT *elem;
+ int len = BN_num_bytes(e->prime);
- x = BN_bin2bn(val, e->prime_len, NULL);
- y = BN_bin2bn(val + e->prime_len, e->prime_len, NULL);
+ x = BN_bin2bn(val, len, NULL);
+ y = BN_bin2bn(val + len, len, NULL);
elem = EC_POINT_new(e->group);
if (x == NULL || y == NULL || elem == NULL) {
- BN_free(x);
- BN_free(y);
- EC_POINT_free(elem);
+ BN_clear_free(x);
+ BN_clear_free(y);
+ EC_POINT_clear_free(elem);
return NULL;
}
if (!EC_POINT_set_affine_coordinates_GFp(e->group, elem, x, y,
e->bnctx)) {
- EC_POINT_free(elem);
+ EC_POINT_clear_free(elem);
elem = NULL;
}
- BN_free(x);
- BN_free(y);
+ BN_clear_free(x);
+ BN_clear_free(y);
return (struct crypto_ec_point *) elem;
}