diff --git a/src/hsm/cmd_cipher_sym.c b/src/hsm/cmd_cipher_sym.c index e0c440e..2873ae8 100644 --- a/src/hsm/cmd_cipher_sym.c +++ b/src/hsm/cmd_cipher_sym.c @@ -27,6 +27,70 @@ #include "kek.h" #include "asn1.h" #include "oid.h" +#include "mbedtls/pkcs5.h" +#include "mbedtls/error.h" +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/oid.h" + +/* This is copied from pkcs5.c Mbedtls */ +/** Unfortunately it is declared as static, so I cannot call it. **/ + +static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations, + int *keylen, mbedtls_md_type_t *md_type ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf prf_alg_oid; + unsigned char *p = params->p; + const unsigned char *end = params->p + params->len; + + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + /* + * PBKDF2-params ::= SEQUENCE { + * salt OCTET STRING, + * iterationCount INTEGER, + * keyLength INTEGER OPTIONAL + * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 + * } + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + + salt->p = p; + p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + } + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + + if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} int cmd_cipher_sym() { int key_id = P1(apdu); @@ -145,7 +209,7 @@ int cmd_cipher_sym() { else if (algo == ALGO_EXT_CIPHER_DECRYPT) res_APDU_size = enc_len - 16; } - else if (memcmp(oid, OID_HMAC, 7) == 0) { + else if (memcmp(oid, OID_DIGEST, 7) == 0) { const mbedtls_md_info_t *md_info = NULL; if (memcmp(oid, OID_HMAC_SHA1, oid_len) == 0) md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); @@ -160,6 +224,7 @@ int cmd_cipher_sym() { if (md_info == NULL) return SW_WRONG_DATA(); int r = mbedtls_md_hmac(md_info, kdata, key_size, apdu.data, apdu.nc, res_APDU); + mbedtls_platform_zeroize(kdata, sizeof(kdata)); if (r != 0) return SW_EXEC_ERROR(); res_APDU_size = md_info->size; @@ -177,6 +242,30 @@ int cmd_cipher_sym() { if (r != 0) return SW_EXEC_ERROR(); } + else if (memcmp(oid, OID_PKCS5_PBKDF2, oid_len) == 0) { + int iterations = 0, keylen = 0; + mbedtls_asn1_buf salt, params = { .p = enc, .len = enc_len }; + mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; + mbedtls_md_context_t md_ctx; + + int r = pkcs5_parse_pbkdf2_params(¶ms, &salt, &iterations, &keylen, &md_type); + if (r != 0) { + mbedtls_platform_zeroize(kdata, sizeof(kdata)); + return SW_WRONG_DATA(); + } + + mbedtls_md_init(&md_ctx); + if (mbedtls_md_setup(&md_ctx, mbedtls_md_info_from_type(md_type), 1) != 0) { + mbedtls_md_free(&md_ctx); + mbedtls_platform_zeroize(kdata, sizeof(kdata)); + return SW_WRONG_DATA(); + } + r = mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, kdata, key_size, salt.p, salt.len, iterations, keylen ? keylen : (apdu.ne ? apdu.ne : apdu.nc), res_APDU); + mbedtls_platform_zeroize(kdata, sizeof(kdata)); + mbedtls_md_free(&md_ctx); + if (r != 0) + return SW_EXEC_ERROR(); + } } else { mbedtls_platform_zeroize(kdata, sizeof(kdata)); diff --git a/src/hsm/oid.h b/src/hsm/oid.h index 6906a8a..800019f 100644 --- a/src/hsm/oid.h +++ b/src/hsm/oid.h @@ -103,20 +103,30 @@ #define OID_CC_FF_PKA OID_CC_FORMAT "\x03" #define OID_CC_FF_KDA OID_CC_FORMAT "\x04" -#define OID_PKCS1_RSADSI "\x2A\x86\x48\x86\xF7\x0D" -#define OID_PKCS9_SMIME_ALG OID_PKCS1_RSADSI "\x01\x09\x10\x03" +#define OID_RSADSI "\x2A\x86\x48\x86\xF7\x0D" + +#define OID_PKCS OID_RSADSI "\x01" + +#define OID_PKCS_5 OID_PKCS "\x05" +#define OID_PKCS5_PBKDF2 OID_PKCS_5 "\x0C" +#define OID_PKCS5_PBES2 OID_PKCS_5 "\x0D" + +#define OID_PKCS_9 OID_PKCS "\x09" + +#define OID_PKCS9_SMIME_ALG OID_PKCS_9 "\x10\x03" #define OID_CHACHA20_POLY1305 OID_PKCS9_SMIME_ALG "\x12" #define OID_HKDF_SHA256 OID_PKCS9_SMIME_ALG "\x1D" #define OID_HKDF_SHA384 OID_PKCS9_SMIME_ALG "\x1E" #define OID_HKDF_SHA512 OID_PKCS9_SMIME_ALG "\x1F" -#define OID_HMAC OID_PKCS1_RSADSI "\x02" -#define OID_HMAC_SHA1 OID_HMAC "\x07" -#define OID_HMAC_SHA224 OID_HMAC "\x08" -#define OID_HMAC_SHA256 OID_HMAC "\x09" -#define OID_HMAC_SHA384 OID_HMAC "\x0A" -#define OID_HMAC_SHA512 OID_HMAC "\x0B" +#define OID_DIGEST OID_RSADSI "\x02" + +#define OID_HMAC_SHA1 OID_DIGEST "\x07" +#define OID_HMAC_SHA224 OID_DIGEST "\x08" +#define OID_HMAC_SHA256 OID_DIGEST "\x09" +#define OID_HMAC_SHA384 OID_DIGEST "\x0A" +#define OID_HMAC_SHA512 OID_DIGEST "\x0B" #endif