Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions include/cose/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,68 @@ void cose_crypto_keypair_ecdsa(cose_key_t *key, cose_curve_t curve);
* @return Signature size
*/
size_t cose_crypto_sig_size_ed25519(void);

/** @} */

/**
* @name HKDF related functions
* @{
*/

/**
* @brief Decide whether a given algorithm is known and an HKDF algorithm
*
* @param alg the algorithm to be checked
*
* @return true if alg can be used with cose_crypto_hkdf_derive
*/
bool cose_crypto_is_hkdf(cose_algo_t alg);

/**
* @brief Derive a key using HKDF (HMAC based key derivation function)
*
* @param salt salt for key generation. Can be empty
* @param salt_len salt length
* @param ikm input key material
* @param ikm_length input key material length
* @param info info for derived key
* @param info_length info for derived key length
* @param[out] out output buffer for derived key
* @param out_length dervied key length
* @param alg HKDF algorithm to use
*
* @return COSE_OK on successful key derivations
* @return COSE_ERR_NOTIMPLEMENTED if the alg is unsupported
* @return COSE_ERR_INVALID_PARAM on invalid salt length
* @return COSE_ERR_CRYPTO otherwise
*/
int cose_crypto_hkdf_derive(const uint8_t *salt, size_t salt_len,
const uint8_t *ikm, size_t ikm_length,
const uint8_t *info, size_t info_length,
uint8_t *out, size_t out_length,
cose_algo_t alg);

/**
* @brief Derive a key using SHA256 HKDF (HMAC based key derivation function)
*
* @param salt salt for key generation. Can be empty
* @param salt_len salt length
* @param ikm input key material
* @param ikm_length input key material length
* @param info info for derived key
* @param info_length info for derived key length
* @param[out] out output buffer for derived key
* @param out_length dervied key length
*
* @return COSE_OK on successful key derivations
* @return COSE_ERR_INVALID_PARAM on invalid salt length
* @return COSE_ERR_CRYPTO otherwise
*/
int cose_crypto_hkdf_derive_sha256(const uint8_t *salt, size_t salt_len,
const uint8_t *ikm, size_t ikm_length,
const uint8_t *info, size_t info_length,
uint8_t *out, size_t out_length);

/** @} */

#ifdef __cplusplus
Expand Down
13 changes: 13 additions & 0 deletions include/cose/crypto/selectors.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@
#define CRYPTO_HACL_INCLUDE_CHACHAPOLY
#endif
/** @} */

/**
*
* @name HKDF SHA256 selector
*/
#if defined(CRYPTO_SODIUM)
#define CRYPTO_SODIUM_INCLUDE_HKDFSHA256
#elif defined(CRYPTO_TINYCRYPT)
#if __has_include (<tinycrypt/hkdf.h>)
#define CRYPTO_TINYCRYPT_INCLUDE_HKDFSHA256
#endif
#endif

#endif /* COSE_CRYPTO_SELECTORS_H */

#if defined(HAVE_ALGO_AES128GCM) || \
Expand Down
1 change: 1 addition & 0 deletions include/cose/crypto/sodium.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extern "C" {
*/
#define HAVE_ALGO_CHACHA20POLY1305
#define HAVE_ALGO_EDDSA
#define HAVE_ALGO_HMAC256
/** @} */

#ifdef __cplusplus
Expand Down
3 changes: 3 additions & 0 deletions include/cose/crypto/tinycrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ extern "C" {
#define HAVE_CURVE_P256 /**< EC NIST p256 curve support */

#define HAVE_ALGO_AESCCM
#if __has_include (<tinycrypt/hkdf.h>)
#define HAVE_ALGO_HMAC256
#endif

#define HAVE_ALGO_AESCCM_16_64_128 /**< AES CCM mode support with 16 bit length, 64 bit tag 128 bit key */
#define HAVE_ALGO_AESCCM_16_128_128 /**< AES CCM mode support with 16 bit length, 128 bit tag 128 bit key */
Expand Down
1 change: 1 addition & 0 deletions include/cose_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ typedef enum {
COSE_ALGO_A128GCM = 1, /**< AES-GCM mode w/ 128-bit key, 128-bit tag */
COSE_ALGO_A192GCM = 2, /**< AES-GCM mode w/ 192-bit key, 128-bit tag */
COSE_ALGO_A256GCM = 3, /**< AES-GCM mode w/ 256-bit key, 128-bit tag */
COSE_ALGO_HMAC256 = 5, /**< HMAC w/ SHA-256 */

COSE_ALGO_AESCCM_16_64_128 = 10, /**< AES-CCM w/ 128-bit key, 64-bit tag and 13-byte nonce */
COSE_ALGO_AESCCM_16_64_256 = 11, /**< AES-CCM w/ 256-bit key, 64-bit tag and 13-byte nonce */
Expand Down
51 changes: 51 additions & 0 deletions src/cose_hkdf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2018 Freie Universitat Berlin
* Copyright (C) 2018 Inria
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

#include "cose/crypto.h"

bool cose_crypto_is_hkdf(cose_algo_t alg)
{
/* NOLINTNEXTLINE(hicpp-multiway-paths-covered) */
switch (alg) {
#ifdef HAVE_ALGO_HMAC256
case COSE_ALGO_HMAC256:
return true;
#endif
default:
(void)alg;
return false;
}
}

int cose_crypto_hkdf_derive(const uint8_t *salt, size_t salt_len,
const uint8_t *ikm, size_t ikm_length,
const uint8_t *info, size_t info_length,
uint8_t *out, size_t out_length,
cose_algo_t alg)
{
/* NOLINTNEXTLINE(hicpp-multiway-paths-covered) */
switch (alg) {
#ifdef HAVE_ALGO_HMAC256
case COSE_ALGO_HMAC256:
return cose_crypto_hkdf_derive_sha256(salt, salt_len, ikm,
ikm_length, info, info_length, out, out_length);
#endif
default:
(void)salt;
(void)salt_len;
(void)ikm;
(void)ikm_length;
(void)info;
(void)info_length;
(void)out;
(void)out_length;
(void)alg;
return COSE_ERR_NOTIMPLEMENTED;
}
}
55 changes: 55 additions & 0 deletions src/crypt/sodium.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <sodium/crypto_aead_chacha20poly1305.h>
#include <sodium/crypto_sign.h>
#include <sodium/randombytes.h>
#include <sodium/crypto_auth_hmacsha256.h>
#include <stdint.h>
#include <stdlib.h>

Expand Down Expand Up @@ -92,3 +93,57 @@ size_t cose_crypto_sig_size_ed25519(void)
return crypto_sign_BYTES;
}
#endif /* CRYPTO_SODIUM_INCLUDE_ED25519 */

#ifdef CRYPTO_SODIUM_INCLUDE_HKDFSHA256
int cose_crypto_hkdf_derive_sha256(const uint8_t *salt, size_t salt_len,
const uint8_t *ikm, size_t ikm_length,
const uint8_t *info, size_t info_length,
uint8_t *out, size_t out_length)
{
uint8_t prk[crypto_auth_hmacsha256_KEYBYTES];

if (salt_len == crypto_auth_hmacsha256_KEYBYTES) {
crypto_auth_hmacsha256(prk, ikm, ikm_length, salt);
}
else if (salt_len < crypto_auth_hmacsha256_KEYBYTES) {
uint8_t padding[crypto_auth_hmacsha256_KEYBYTES];
memset(padding, 0, crypto_auth_hmacsha256_KEYBYTES);
if (salt) {
memcpy(padding, salt, salt_len);
}
crypto_auth_hmacsha256(prk, ikm, ikm_length, padding);
}
else {
return COSE_ERR_INVALID_PARAM;
}

uint8_t slice[crypto_auth_hmacsha256_BYTES];
size_t slice_len = crypto_auth_hmacsha256_BYTES;
uint8_t counter[1] = { 0x01 };
crypto_auth_hmacsha256_state state;
size_t rounds = out_length / crypto_auth_hmacsha256_BYTES;

if (out_length % crypto_auth_hmacsha256_BYTES > 0) {
rounds++;
}
for (size_t i = 0; i < rounds; ++i) {
size_t offset = i * crypto_auth_hmacsha256_BYTES;
*counter = i + 1;
crypto_auth_hmacsha256_init(&state, prk, crypto_auth_hmacsha256_KEYBYTES);
if (i > 0) {
crypto_auth_hmacsha256_update(&state, slice, slice_len);
}
if (info) {
crypto_auth_hmacsha256_update(&state, info, info_length);
}
crypto_auth_hmacsha256_update(&state, counter, 1);
crypto_auth_hmacsha256_final(&state, slice);
if (i + 1 == rounds) {
slice_len = out_length - offset;
}
memcpy(out + offset, slice, slice_len);
}

return COSE_OK;
}
#endif /* CRYPTO_SODIUM_INCLUDE_HKDFSHA256 */
26 changes: 26 additions & 0 deletions src/crypt/tinycrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#include <tinycrypt/ecc_dh.h>
#include <tinycrypt/ecc_dsa.h>
#include <tinycrypt/sha256.h>
#if __has_include (<tinycrypt/hkdf.h>)
#include <tinycrypt/hkdf.h>
#endif

extern cose_crypt_rng cose_crypt_get_random;
extern void *cose_crypt_rng_arg;
Expand Down Expand Up @@ -188,3 +191,26 @@ int cose_crypto_verify_ecdsa(const cose_key_t *key, const uint8_t *sign, size_t
int res = uECC_verify(pubkey, hash, sizeof(hash), (uint8_t*)sign, uECC_secp256r1());
return res ? COSE_OK : COSE_ERR_CRYPTO;
}

#ifdef CRYPTO_TINYCRYPT_INCLUDE_HKDFSHA256
int cose_crypto_hkdf_derive_sha256(const uint8_t *salt, size_t salt_len,
const uint8_t *ikm, size_t ikm_length,
const uint8_t *info, size_t info_length,
uint8_t *out, size_t out_length)
{
uint8_t prk[TC_SHA256_DIGEST_SIZE];

int ret = tc_hkdf_extract(ikm, ikm_length, salt, salt_len, prk);

if (ret != TC_CRYPTO_SUCCESS) {
return COSE_ERR_CRYPTO;
}

ret = tc_hkdf_expand(prk, info, info_length, out_length, out);

if (ret != TC_CRYPTO_SUCCESS) {
return COSE_ERR_CRYPTO;
}
return COSE_OK;
}
#endif /* CRYPTO_TINYCRYPT_INCLUDE_HKDFSHA256 */
Loading