* Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
* Copyright (C) 2013 Hauke Mehrtens <hauke@hauke-m.de>
*
+ *
+ * Modified source code for micro-ecc porting,
+ *
+ * Following functions are removed:
+ * - dtls_ec_key_to_uint32
+ * - dtls_ec_key_from_uint32
+ * Following functions are modified:
+ * - dtls_ecdh_pre_master_secret
+ * - dtls_ecdsa_generate_key
+ * - dtls_ecdsa_create_sig_hash
+ * - dtls_ecdsa_verify_sig_hash
+ *
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
#include "crypto.h"
#include "ccm.h"
#include "ecc/ecc.h"
+#include "aes/rijndael.h"
+#include "sha2/sha2.h"
#include "prng.h"
#include "netq.h"
/* initialize the handshake hash wrt. the hard-coded DTLS version */
dtls_debug("DTLSv12: initialize HASH_SHA256\n");
/* TLS 1.2: PRF(secret, label, seed) = P_<hash>(secret, label + seed) */
- /* FIXME: we use the default SHA256 here, might need to support other
+ /* FIXME: we use the default SHA256 here, might need to support other
hash functions as well */
dtls_hash_init(&handshake->hs_state.hs_hash);
}
dtls_hmac_init(hmac_p, key, keylen);
dtls_hmac_update(hmac_p, A, dlen);
-
+
HMAC_UPDATE_SEED(hmac_p, label, labellen);
HMAC_UPDATE_SEED(hmac_p, random1, random1len);
HMAC_UPDATE_SEED(hmac_p, random2, random2len);
-
+
dtls_hmac_finalize(hmac_p, tmp);
memcpy(buf, tmp, buflen - len);
return buflen;
}
-size_t
+size_t
dtls_prf(const unsigned char *key, size_t keylen,
const unsigned char *label, size_t labellen,
const unsigned char *random1, size_t random1len,
/* Clear the result buffer */
memset(buf, 0, buflen);
- return dtls_p_hash(HASH_SHA256,
- key, keylen,
- label, labellen,
+ return dtls_p_hash(HASH_SHA256,
+ key, keylen,
+ label, labellen,
random1, random1len,
random2, random2len,
buf, buflen);
}
void
-dtls_mac(dtls_hmac_context_t *hmac_ctx,
+dtls_mac(dtls_hmac_context_t *hmac_ctx,
const unsigned char *record,
const unsigned char *packet, size_t length,
unsigned char *buf) {
dtls_hmac_update(hmac_ctx, record, sizeof(uint8) + sizeof(uint16));
dtls_hmac_update(hmac_ctx, L, sizeof(uint16));
dtls_hmac_update(hmac_ctx, packet, length);
-
+
dtls_hmac_finalize(hmac_ctx, buf);
}
static size_t
-dtls_ccm_encrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src, size_t srclen,
- unsigned char *buf,
+dtls_ccm_encrypt(aes128_t *ccm_ctx, const unsigned char *src, size_t srclen,
+ unsigned char *buf,
unsigned char *nounce,
const unsigned char *aad, size_t la) {
long int len;
assert(ccm_ctx);
- len = dtls_ccm_encrypt_message(&ccm_ctx->ctx, 8 /* M */,
+ len = dtls_ccm_encrypt_message(&ccm_ctx->ctx, 8 /* M */,
max(2, 15 - DTLS_CCM_NONCE_SIZE),
nounce,
- buf, srclen,
+ buf, srclen,
aad, la);
return len;
}
static size_t
-dtls_ccm_decrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src,
+dtls_ccm_decrypt(aes128_t *ccm_ctx, const unsigned char *src,
size_t srclen, unsigned char *buf,
unsigned char *nounce,
const unsigned char *aad, size_t la) {
assert(ccm_ctx);
- len = dtls_ccm_decrypt_message(&ccm_ctx->ctx, 8 /* M */,
+ len = dtls_ccm_decrypt_message(&ccm_ctx->ctx, 8 /* M */,
max(2, 15 - DTLS_CCM_NONCE_SIZE),
nounce,
- buf, srclen,
+ buf, srclen,
aad, la);
return len;
}
+static size_t
+dtls_cbc_encrypt(aes128_t *aes_ctx,
+ const unsigned char *iv,
+ const unsigned char *src, size_t srclen,
+ unsigned char *buf) {
+
+ unsigned char cbc[DTLS_BLK_LENGTH];
+ unsigned char tmp[DTLS_BLK_LENGTH];
+ unsigned char *pos;
+ dtls_hash_ctx shactx;
+ int i, j;
+ int blocks;
+
+ pos = buf;
+
+ dtls_hash_init(&shactx);
+ dtls_hash_update(&shactx, src, srclen);
+ dtls_hash_finalize(pos + srclen, &shactx);
+
+ memcpy(cbc, iv, DTLS_BLK_LENGTH);
+ blocks = (srclen + SHA256_DIGEST_LENGTH) / DTLS_BLK_LENGTH;
+
+ for (i = 0; i < blocks; i++) {
+ for (j = 0; j < DTLS_BLK_LENGTH; j++) {
+ cbc[j] ^= pos[j];
+ }
+
+ rijndael_encrypt(&aes_ctx->ctx, cbc, tmp);
+ memcpy(cbc, tmp, DTLS_BLK_LENGTH);
+ memcpy(pos, cbc, DTLS_BLK_LENGTH);
+ pos += DTLS_BLK_LENGTH;
+ }
+
+ dtls_debug_dump("Encrypted Data:", buf, srclen + SHA256_DIGEST_LENGTH);
+
+ return srclen + SHA256_DIGEST_LENGTH;
+}
+
+
+static size_t
+dtls_cbc_decrypt(aes128_t *aes_ctx,
+ const unsigned char *iv,
+ const unsigned char *src, size_t srclen,
+ unsigned char *buf) {
+
+ unsigned char cbc[DTLS_BLK_LENGTH];
+ unsigned char tmp[DTLS_BLK_LENGTH];
+ unsigned char tmp2[DTLS_BLK_LENGTH];
+ unsigned char msg_hash[SHA256_DIGEST_LENGTH];
+ unsigned char *pos;
+ dtls_hash_ctx shactx;
+ int i, j;
+ int blocks;
+
+ pos = buf;
+ memcpy(pos, src, srclen);
+
+ memcpy(cbc, iv, DTLS_BLK_LENGTH);
+ blocks = srclen / DTLS_BLK_LENGTH;
+
+ for (i = 0; i < blocks; i++)
+ {
+ memcpy(tmp, pos, DTLS_BLK_LENGTH);
+ rijndael_decrypt(&aes_ctx->ctx, pos, tmp2);
+ memcpy(pos, tmp2, DTLS_BLK_LENGTH);
+
+ for (j = 0; j < DTLS_BLK_LENGTH; j++) {
+ pos[j] ^= cbc[j];
+ }
+
+ memcpy(cbc, tmp, DTLS_BLK_LENGTH);
+ pos += DTLS_BLK_LENGTH;
+ }
+
+ dtls_hash_init(&shactx);
+ dtls_hash_update(&shactx, buf, srclen - SHA256_DIGEST_LENGTH);
+ dtls_hash_finalize(msg_hash, &shactx);
+
+ dtls_debug_dump("decrypted data:", buf, srclen);
+
+ if(memcmp(msg_hash, buf + (srclen - SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH) != 0)
+ {
+ dtls_warn("message is broken\n");
+ return -1;
+ }
+
+ return srclen - SHA256_DIGEST_LENGTH;
+}
+
#ifdef DTLS_PSK
int
dtls_psk_pre_master_secret(unsigned char *key, size_t keylen,
memcpy(p, result, sizeof(uint16));
p += sizeof(uint16);
-
+
memcpy(p, key, keylen);
return 2 * (sizeof(uint16) + keylen);
#endif /* DTLS_PSK */
#ifdef DTLS_ECC
-static void dtls_ec_key_to_uint32(const unsigned char *key, size_t key_size,
- uint32_t *result) {
- int i;
-
- for (i = (key_size / sizeof(uint32_t)) - 1; i >= 0 ; i--) {
- *result = dtls_uint32_to_int(&key[i * sizeof(uint32_t)]);
- result++;
- }
-}
-
-static void dtls_ec_key_from_uint32(const uint32_t *key, size_t key_size,
- unsigned char *result) {
- int i;
-
- for (i = (key_size / sizeof(uint32_t)) - 1; i >= 0 ; i--) {
- dtls_int_to_uint32(result, key[i]);
- result += 4;
- }
-}
int dtls_ec_key_from_uint32_asn1(const uint32_t *key, size_t key_size,
unsigned char *buf) {
int i;
unsigned char *buf_orig = buf;
- int first = 1;
+ int first = 1;
for (i = (key_size / sizeof(uint32_t)) - 1; i >= 0 ; i--) {
if (key[i] == 0)
*buf = 0;
buf++;
dtls_int_to_uint32(buf, key[i]);
- buf += 4;
+ buf += 4;
} else if (first && !(key[i] & 0xFF800000)) {
buf[0] = (key[i] >> 16) & 0xff;
buf[1] = (key[i] >> 8) & 0xff;
size_t key_size,
unsigned char *result,
size_t result_len) {
- uint32_t priv[8];
- uint32_t pub_x[8];
- uint32_t pub_y[8];
- uint32_t result_x[8];
- uint32_t result_y[8];
+
+ uint8_t publicKey[64];
+ uint8_t privateKey[32];
if (result_len < key_size) {
return -1;
}
- dtls_ec_key_to_uint32(priv_key, key_size, priv);
- dtls_ec_key_to_uint32(pub_key_x, key_size, pub_x);
- dtls_ec_key_to_uint32(pub_key_y, key_size, pub_y);
- ecc_ecdh(pub_x, pub_y, priv, result_x, result_y);
+ memcpy(publicKey, pub_key_x, 32);
+ memcpy(publicKey + 32, pub_key_y, 32);
+ memcpy(privateKey, priv_key, 32);
+ uECC_shared_secret(publicKey, privateKey, result);
- dtls_ec_key_from_uint32(result_x, key_size, result);
return key_size;
}
unsigned char *pub_key_x,
unsigned char *pub_key_y,
size_t key_size) {
- uint32_t priv[8];
- uint32_t pub_x[8];
- uint32_t pub_y[8];
- do {
- dtls_prng((unsigned char *)priv, key_size);
- } while (!ecc_is_valid_key(priv));
+ uint8_t publicKey[64];
+ uint8_t privateKey[32];
- ecc_gen_pub_key(priv, pub_x, pub_y);
+ uECC_make_key(publicKey, privateKey);
+ memcpy(pub_key_x, publicKey, 32);
+ memcpy(pub_key_y, publicKey + 32, 32);
+ memcpy(priv_key, privateKey, 32);
- dtls_ec_key_from_uint32(priv, key_size, priv_key);
- dtls_ec_key_from_uint32(pub_x, key_size, pub_key_x);
- dtls_ec_key_from_uint32(pub_y, key_size, pub_key_y);
}
/* rfc4492#section-5.4 */
const unsigned char *sign_hash, size_t sign_hash_size,
uint32_t point_r[9], uint32_t point_s[9]) {
int ret;
- uint32_t priv[8];
- uint32_t hash[8];
- uint32_t rand[8];
-
- dtls_ec_key_to_uint32(priv_key, key_size, priv);
- dtls_ec_key_to_uint32(sign_hash, sign_hash_size, hash);
- do {
- dtls_prng((unsigned char *)rand, key_size);
- ret = ecc_ecdsa_sign(priv, hash, rand, point_r, point_s);
- } while (ret);
+
+ uint8_t privateKey[32];
+ uint8_t hashValue[32];
+ uint8_t sign[64];
+
+
+ uECC_sign(privateKey, hashValue, sign);
+ memcpy(point_r, sign, 32);
+ memcpy(point_s, sign + 32, 32);
}
void
dtls_hash_update(&data, server_random, server_random_size);
dtls_hash_update(&data, keyx_params, keyx_params_size);
dtls_hash_finalize(sha256hash, &data);
-
+
dtls_ecdsa_create_sig_hash(priv_key, key_size, sha256hash,
sizeof(sha256hash), point_r, point_s);
}
const unsigned char *pub_key_y, size_t key_size,
const unsigned char *sign_hash, size_t sign_hash_size,
unsigned char *result_r, unsigned char *result_s) {
- uint32_t pub_x[8];
- uint32_t pub_y[8];
- uint32_t hash[8];
- uint32_t point_r[8];
- uint32_t point_s[8];
- dtls_ec_key_to_uint32(pub_key_x, key_size, pub_x);
- dtls_ec_key_to_uint32(pub_key_y, key_size, pub_y);
- dtls_ec_key_to_uint32(result_r, key_size, point_r);
- dtls_ec_key_to_uint32(result_s, key_size, point_s);
- dtls_ec_key_to_uint32(sign_hash, sign_hash_size, hash);
+ uint8_t publicKey[64];
+ uint8_t hashValue[32];
+ uint8_t sign[64];
- return ecc_ecdsa_validate(pub_x, pub_y, hash, point_r, point_s);
+ memcpy(publicKey, pub_key_x, 32);
+ memcpy(publicKey + 32, pub_key_y, 32);
+ return uECC_verify(publicKey, hashValue, sign);
}
int
unsigned char *result_r, unsigned char *result_s) {
dtls_hash_ctx data;
unsigned char sha256hash[DTLS_HMAC_DIGEST_SIZE];
-
+
dtls_hash_init(&data);
dtls_hash_update(&data, client_random, client_random_size);
dtls_hash_update(&data, server_random, server_random_size);
}
#endif /* DTLS_ECC */
-int
+int
dtls_encrypt(const unsigned char *src, size_t length,
unsigned char *buf,
unsigned char *nounce,
unsigned char *key, size_t keylen,
- const unsigned char *aad, size_t la)
+ const unsigned char *aad, size_t la,
+ const dtls_cipher_t cipher)
{
- int ret;
+ int ret = 0;
struct dtls_cipher_context_t *ctx = dtls_cipher_context_get();
- ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen);
- if (ret < 0) {
- /* cleanup everything in case the key has the wrong size */
- dtls_warn("cannot set rijndael key\n");
- goto error;
+ if(cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ||
+ cipher == TLS_PSK_WITH_AES_128_CCM_8) {
+ ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen);
+ if (ret < 0) {
+ /* cleanup everything in case the key has the wrong size */
+ dtls_warn("cannot set rijndael key\n");
+ goto error;
+ }
+
+ if (src != buf)
+ memmove(buf, src, length);
+ ret = dtls_ccm_encrypt(&ctx->data, src, length, buf, nounce, aad, la);
+ }
+ if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA) {
+ ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
+ if (ret < 0) {
+ /* cleanup everything in case the key has the wrong size */
+ dtls_warn("cannot set rijndael key\n");
+ goto error;
+ }
+
+ if (src != buf)
+ memmove(buf, src, length);
+ ret = dtls_cbc_encrypt(&ctx->data, nounce, src, length, buf);
}
-
- if (src != buf)
- memmove(buf, src, length);
- ret = dtls_ccm_encrypt(&ctx->data, src, length, buf, nounce, aad, la);
error:
dtls_cipher_context_release();
return ret;
}
-int
+int
dtls_decrypt(const unsigned char *src, size_t length,
unsigned char *buf,
unsigned char *nounce,
unsigned char *key, size_t keylen,
- const unsigned char *aad, size_t la)
+ const unsigned char *aad, size_t la,
+ const dtls_cipher_t cipher)
{
- int ret;
+ int ret = 0;
struct dtls_cipher_context_t *ctx = dtls_cipher_context_get();
- ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen);
- if (ret < 0) {
- /* cleanup everything in case the key has the wrong size */
- dtls_warn("cannot set rijndael key\n");
- goto error;
+ if(cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ||
+ cipher == TLS_PSK_WITH_AES_128_CCM_8) {
+ ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen);
+ if (ret < 0) {
+ /* cleanup everything in case the key has the wrong size */
+ dtls_warn("cannot set rijndael key\n");
+ goto error;
+ }
+
+ if (src != buf)
+ memmove(buf, src, length);
+ ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce, aad, la);
}
- if (src != buf)
- memmove(buf, src, length);
- ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce, aad, la);
+ if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA) {
+ ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
+ if (ret < 0) {
+ /* cleanup everything in case the key has the wrong size */
+ dtls_warn("cannot set rijndael key\n");
+ goto error;
+ }
+
+ if (src != buf)
+ memmove(buf, src, length);
+ ret = dtls_cbc_decrypt(&ctx->data, nounce, src, length, buf);
+ }
error:
dtls_cipher_context_release();