diff options
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/crypt.c | 38 | ||||
| -rw-r--r-- | src/lib/crypt/openssl.c | 113 | ||||
| -rw-r--r-- | src/lib/crypt/openssl.h | 265 | ||||
| -rw-r--r-- | src/lib/tests/kex_test.c | 19 | ||||
| -rw-r--r-- | src/lib/tests/kex_test_ml_kem.c | 8 |
5 files changed, 194 insertions, 249 deletions
diff --git a/src/lib/crypt.c b/src/lib/crypt.c index bc3dcd16..35007ef3 100644 --- a/src/lib/crypt.c +++ b/src/lib/crypt.c @@ -378,14 +378,16 @@ ssize_t kex_kem_encap(buffer_t pk, #endif } -ssize_t kex_kem_encap_raw(buffer_t pk, - uint8_t * ct, - int kdf, - uint8_t * s) +ssize_t kex_kem_encap_raw(const char * algo, + buffer_t pk, + uint8_t * ct, + int kdf, + uint8_t * s) { #ifdef HAVE_OPENSSL - return openssl_kem_encap_raw(pk, ct, kdf, s); + return openssl_kem_encap_raw(algo, pk, ct, kdf, s); #else + (void) algo; (void) pk; (void) ct; (void) kdf; @@ -427,19 +429,6 @@ int kex_get_algo_from_pk_der(buffer_t pk, #endif } -int kex_get_algo_from_pk_raw(buffer_t pk, - char * algo) -{ -#ifdef HAVE_OPENSSL - return openssl_get_algo_from_pk_raw(pk, algo); -#else - (void) pk; - algo[0] = '\0'; - - return -ECRYPT; -#endif -} - int kex_validate_algo(const char * algo) { if (algo == NULL) @@ -547,6 +536,11 @@ int kex_validate_nid(int nid) return -ENOTSUP; } +bool kex_nid_is_hybrid(uint16_t nid) +{ + return nid >= NID_HYBRID_KEM_MIN && nid <= NID_HYBRID_KEM_MAX; +} + const char * md_nid_to_str(uint16_t nid) { const struct nid_map * p; @@ -1032,14 +1026,16 @@ int crypt_load_pubkey_file_to_der(const char * path, } int crypt_load_pubkey_raw_file(const char * path, + const char * algo, buffer_t * buf) { assert(buf != NULL); #ifdef HAVE_OPENSSL - return openssl_load_pubkey_raw_file(path, buf); + return openssl_load_pubkey_raw_file(path, algo, buf); #else (void) path; + (void) algo; buf->data = NULL; buf->len = 0; @@ -1048,14 +1044,16 @@ int crypt_load_pubkey_raw_file(const char * path, } int crypt_load_privkey_raw_file(const char * path, + const char * algo, void ** key) { *key = NULL; #ifdef HAVE_OPENSSL - return openssl_load_privkey_raw_file(path, key); + return openssl_load_privkey_raw_file(path, algo, key); #else (void) path; + (void) algo; return 0; #endif diff --git a/src/lib/crypt/openssl.c b/src/lib/crypt/openssl.c index 7716f27f..8ec3b40f 100644 --- a/src/lib/crypt/openssl.c +++ b/src/lib/crypt/openssl.c @@ -721,23 +721,6 @@ static int __openssl_kem_gen_key(const char * algo, return -ECRYPT; } -/* Determine hybrid KEM algorithm from raw key/ciphertext length */ -static const char * __openssl_hybrid_algo_from_len(size_t len) -{ - switch(len) { - case X25519MLKEM768_PKSZ: - return "X25519MLKEM768"; - case X25519MLKEM768_CTSZ: - return "X25519MLKEM768"; - case X448MLKEM1024_PKSZ: - return "X448MLKEM1024"; - default: - break; - } - - return NULL; -} - static int __openssl_kex_gen_key(const char * algo, EVP_PKEY ** kp) { @@ -900,18 +883,19 @@ ssize_t openssl_kem_encap(buffer_t pk, return -ECRYPT; } -/* Hybrid KEM encapsulation: raw-encoded public key */ -ssize_t openssl_kem_encap_raw(buffer_t pk, - uint8_t * ct, - int kdf, - uint8_t * s) +/* Hybrid KEM encapsulation: NID-tagged raw-encoded public key */ +ssize_t openssl_kem_encap_raw(const char * algo, + buffer_t pk, + uint8_t * ct, + int kdf, + uint8_t * s) { - EVP_PKEY * pub; - const char * algo; - uint8_t salt[HKDF_SALT_LEN]; - buffer_t salt_b; - ssize_t ret; + EVP_PKEY * pub; + uint8_t salt[HKDF_SALT_LEN]; + buffer_t salt_b; + ssize_t ret; + assert(algo != NULL); assert(pk.data != NULL); assert(ct != NULL); assert(s != NULL); @@ -922,10 +906,6 @@ ssize_t openssl_kem_encap_raw(buffer_t pk, if (derive_salt_from_pk_bytes(pk, salt_b) < 0) goto fail_salt; - algo = __openssl_hybrid_algo_from_len(pk.len); - if (algo == NULL) - goto fail_salt; - pub = EVP_PKEY_new_raw_public_key_ex(NULL, algo, NULL, pk.data, pk.len); if (pub == NULL) @@ -1071,23 +1051,6 @@ int openssl_get_algo_from_pk_der(buffer_t pk, return -ECRYPT; } -int openssl_get_algo_from_pk_raw(buffer_t pk, - char * algo) -{ - const char * hybrid_algo; - - assert(pk.data != NULL); - assert(algo != NULL); - - hybrid_algo = __openssl_hybrid_algo_from_len(pk.len); - if (hybrid_algo == NULL) - return -ECRYPT; - - strcpy(algo, hybrid_algo); - - return 0; -} - int openssl_dhe_derive(EVP_PKEY * pkp, buffer_t pk, int kdf, @@ -1519,14 +1482,16 @@ int openssl_load_pubkey_str(const char * str, } int openssl_load_pubkey_raw_file(const char * path, + const char * algo, buffer_t * buf) { - FILE * fp; - uint8_t tmp_buf[CRYPT_KEY_BUFSZ]; - size_t bytes_read; - const char * algo; + FILE * fp; + uint8_t tmp_buf[CRYPT_KEY_BUFSZ]; + size_t bytes_read; + EVP_PKEY * chk; assert(path != NULL); + assert(algo != NULL); assert(buf != NULL); fp = fopen(path, "rb"); @@ -1539,14 +1504,19 @@ int openssl_load_pubkey_raw_file(const char * path, pthread_cleanup_pop(false); - if (bytes_read == 0) + /* A full buffer means the file was truncated */ + if (bytes_read == 0 || bytes_read == CRYPT_KEY_BUFSZ) goto fail_read; - /* Validate that this is a known hybrid KEM format */ - algo = __openssl_hybrid_algo_from_len(bytes_read); - if (algo == NULL) + /* Trial import: reject bad keys at load time */ + chk = EVP_PKEY_new_raw_public_key_ex(NULL, algo, NULL, + tmp_buf, bytes_read); + + if (chk == NULL) goto fail_read; + EVP_PKEY_free(chk); + buf->data = malloc(bytes_read); if (buf->data == NULL) goto fail_malloc; @@ -1565,21 +1535,6 @@ int openssl_load_pubkey_raw_file(const char * path, return -1; } -/* Determine hybrid KEM algorithm from raw private key length */ -static const char * __openssl_hybrid_algo_from_sk_len(size_t len) -{ - switch(len) { - case X25519MLKEM768_SKSZ: - return "X25519MLKEM768"; - case X448MLKEM1024_SKSZ: - return "X448MLKEM1024"; - default: - break; - } - - return NULL; -} - /* Wipe the raw-key staging buffer if a cancel aborts the read. */ static void __cleanse_key_buf(void * o) { @@ -1587,15 +1542,16 @@ static void __cleanse_key_buf(void * o) } int openssl_load_privkey_raw_file(const char * path, + const char * algo, void ** key) { - FILE * fp; - uint8_t tmp_buf[CRYPT_KEY_BUFSZ]; - size_t bytes_read; - const char * algo; - EVP_PKEY * pkey; + FILE * fp; + uint8_t tmp_buf[CRYPT_KEY_BUFSZ]; + size_t bytes_read; + EVP_PKEY * pkey; assert(path != NULL); + assert(algo != NULL); assert(key != NULL); fp = fopen(path, "rb"); @@ -1613,11 +1569,6 @@ int openssl_load_privkey_raw_file(const char * path, if (bytes_read == 0) goto fail_read; - /* Determine algorithm from key size */ - algo = __openssl_hybrid_algo_from_sk_len(bytes_read); - if (algo == NULL) - goto fail_read; - pkey = EVP_PKEY_new_raw_private_key_ex(NULL, algo, NULL, tmp_buf, bytes_read); /* Clear sensitive data from stack */ diff --git a/src/lib/crypt/openssl.h b/src/lib/crypt/openssl.h index e5cc35f7..6857e39b 100644 --- a/src/lib/crypt/openssl.h +++ b/src/lib/crypt/openssl.h @@ -28,72 +28,70 @@ struct ossl_crypt_ctx; -ssize_t openssl_pkp_create(const char * algo, - EVP_PKEY ** pkp, - uint8_t * pk); +ssize_t openssl_pkp_create(const char * algo, + EVP_PKEY ** pkp, + uint8_t * pk); -void openssl_pkp_destroy(EVP_PKEY * pkp); +void openssl_pkp_destroy(EVP_PKEY * pkp); -int openssl_dhe_derive(EVP_PKEY * pkp, - buffer_t pk, - int kdf_nid, - uint8_t * s); +int openssl_dhe_derive(EVP_PKEY * pkp, + buffer_t pk, + int kdf_nid, + uint8_t * s); -ssize_t openssl_kem_encap(buffer_t pk, - uint8_t * ct, - int kdf_nid, - uint8_t * s); +ssize_t openssl_kem_encap(buffer_t pk, + uint8_t * ct, + int kdf_nid, + uint8_t * s); /* no X509 DER support yet for DHKEM public keys */ -ssize_t openssl_kem_encap_raw(buffer_t pk, - uint8_t * ct, - int kdf_nid, - uint8_t * s); - -int openssl_kem_decap(EVP_PKEY * priv, - buffer_t ct, - int kdf_nid, - uint8_t * s); - -int openssl_get_algo_from_pk_der(buffer_t pk, - char * algo); - -int openssl_get_algo_from_pk_raw(buffer_t pk, - char * algo); - -int openssl_seal(struct ossl_crypt_ctx * ctx, - const uint8_t * key, - const uint8_t * nonce, - buffer_t aad, - buffer_t in, - uint8_t * out, - uint8_t * tag); - -int openssl_open(struct ossl_crypt_ctx * ctx, - const uint8_t * key, - const uint8_t * nonce, - buffer_t aad, - buffer_t in, - const uint8_t * tag, - buffer_t * out); - -int openssl_oneshot_seal(int nid, - const uint8_t * key, - const uint8_t * nonce, - buffer_t aad, - buffer_t in, - buffer_t * out); - -int openssl_oneshot_open(int nid, - const uint8_t * key, - const uint8_t * nonce, - buffer_t aad, - buffer_t in, - buffer_t * out); - -int openssl_hkdf_expand(buffer_t key, - buffer_t info, - buffer_t out); +ssize_t openssl_kem_encap_raw(const char * algo, + buffer_t pk, + uint8_t * ct, + int kdf_nid, + uint8_t * s); + +int openssl_kem_decap(EVP_PKEY * priv, + buffer_t ct, + int kdf_nid, + uint8_t * s); + +int openssl_get_algo_from_pk_der(buffer_t pk, + char * algo); + +int openssl_seal(struct ossl_crypt_ctx * ctx, + const uint8_t * key, + const uint8_t * nonce, + buffer_t aad, + buffer_t in, + uint8_t * out, + uint8_t * tag); + +int openssl_open(struct ossl_crypt_ctx * ctx, + const uint8_t * key, + const uint8_t * nonce, + buffer_t aad, + buffer_t in, + const uint8_t * tag, + buffer_t * out); + +int openssl_oneshot_seal(int nid, + const uint8_t * key, + const uint8_t * nonce, + buffer_t aad, + buffer_t in, + buffer_t * out); + +int openssl_oneshot_open(int nid, + const uint8_t * key, + const uint8_t * nonce, + buffer_t aad, + buffer_t in, + buffer_t * out); + +int openssl_hkdf_expand(buffer_t key, + buffer_t info, + buffer_t out); struct ossl_crypt_ctx * openssl_crypt_create_ctx(struct crypt_sk * sk); @@ -102,112 +100,113 @@ void openssl_crypt_destroy_ctx(struct ossl_crypt_ctx * ctx); int openssl_crypt_get_tagsz(struct ossl_crypt_ctx * ctx); /* AUTHENTICATION */ +int openssl_load_crt_file(const char * path, + void ** crt); -int openssl_load_crt_file(const char * path, - void ** crt); +int openssl_load_crt_str(const char * str, + void ** crt); -int openssl_load_crt_str(const char * str, - void ** crt); +int openssl_load_crt_der(buffer_t buf, + void ** crt); -int openssl_load_crt_der(buffer_t buf, - void ** crt); +int openssl_get_pubkey_crt(void * crt, + void ** pk); -int openssl_get_pubkey_crt(void * crt, - void ** pk); +void openssl_free_crt(void * crt); -void openssl_free_crt(void * crt); +int openssl_load_privkey_file(const char * path, + void ** key); -int openssl_load_privkey_file(const char * path, - void ** key); +int openssl_load_privkey_str(const char * str, + void ** key); -int openssl_load_privkey_str(const char * str, - void ** key); +int openssl_load_pubkey_file(const char * path, + void ** key); -int openssl_load_pubkey_file(const char * path, - void ** key); +int openssl_load_pubkey_str(const char * str, + void ** key); +int openssl_load_pubkey_file_to_der(const char * path, + buffer_t * buf); +int openssl_load_pubkey_raw_file(const char * path, + const char * algo, + buffer_t * buf); -int openssl_load_pubkey_str(const char * str, - void ** key); -int openssl_load_pubkey_file_to_der(const char * path, - buffer_t * buf); -int openssl_load_pubkey_raw_file(const char * path, - buffer_t * buf); - -int openssl_load_privkey_raw_file(const char * path, - void ** key); +int openssl_load_privkey_raw_file(const char * path, + const char * algo, + void ** key); -int openssl_cmp_key(const EVP_PKEY * key1, - const EVP_PKEY * key2); +int openssl_cmp_key(const EVP_PKEY * key1, + const EVP_PKEY * key2); -void openssl_free_key(EVP_PKEY * key); +void openssl_free_key(EVP_PKEY * key); -int openssl_check_crt_name(void * crt, - const char * name); +int openssl_check_crt_name(void * crt, + const char * name); -int openssl_get_crt_name(void * crt, - char * name); +int openssl_get_crt_name(void * crt, + char * name); -int openssl_crt_str(const void * crt, - char * str); +int openssl_crt_str(const void * crt, + char * str); -int openssl_crt_der(const void * crt, - buffer_t * buf); +int openssl_crt_der(const void * crt, + buffer_t * buf); -void * openssl_auth_create_store(void); +void * openssl_auth_create_store(void); -void openssl_auth_destroy_store(void * store); +void openssl_auth_destroy_store(void * store); -int openssl_auth_add_crt_to_store(void * store, - void * crt); +int openssl_auth_add_crt_to_store(void * store, + void * crt); -void * openssl_auth_create_chain(void); +void * openssl_auth_create_chain(void); -void openssl_auth_destroy_chain(void * chain); +void openssl_auth_destroy_chain(void * chain); -int openssl_auth_add_crt_to_chain(void * chain, - void * crt); +int openssl_auth_add_crt_to_chain(void * chain, + void * crt); -int openssl_verify_crt(void * store, - void * untrusted, - void * crt); +int openssl_verify_crt(void * store, + void * untrusted, + void * crt); -int openssl_verify_crt_pin(void * store, - void * untrusted, - void * crt, - void * pin); +int openssl_verify_crt_pin(void * store, + void * untrusted, + void * crt, + void * pin); -bool openssl_pk_requires_md(const EVP_PKEY * pk); +bool openssl_pk_requires_md(const EVP_PKEY * pk); -int openssl_sign(EVP_PKEY * pkp, - int md_nid, - buffer_t msg, - buffer_t * sig); +int openssl_sign(EVP_PKEY * pkp, + int md_nid, + buffer_t msg, + buffer_t * sig); -int openssl_verify_sig(EVP_PKEY * pk, - int md_nid, - buffer_t msg, - buffer_t sig); +int openssl_verify_sig(EVP_PKEY * pk, + int md_nid, + buffer_t msg, + buffer_t sig); -ssize_t openssl_md_digest(int md_nid, - buffer_t in, - uint8_t * out); +ssize_t openssl_md_digest(int md_nid, + buffer_t in, + uint8_t * out); -ssize_t openssl_md_len(int md_nid); +ssize_t openssl_md_len(int md_nid); /* Secure memory allocation */ -int openssl_secure_malloc_init(size_t max, - size_t guard); +int openssl_secure_malloc_init(size_t max, + size_t guard); -void openssl_secure_malloc_fini(void); +void openssl_secure_malloc_fini(void); -void * openssl_secure_malloc(size_t size); +void * openssl_secure_malloc(size_t size); -void openssl_secure_free(void * ptr, - size_t size); +void openssl_secure_free(void * ptr, + size_t size); -void openssl_secure_clear(void * ptr, - size_t size); +void openssl_secure_clear(void * ptr, + size_t size); -void openssl_cleanup(void); +void openssl_cleanup(void); #endif /* OUROBOROS_LIB_CRYPT_OPENSSL_H */ diff --git a/src/lib/tests/kex_test.c b/src/lib/tests/kex_test.c index 38835265..d7629f95 100644 --- a/src/lib/tests/kex_test.c +++ b/src/lib/tests/kex_test.c @@ -182,17 +182,9 @@ static int test_kex_get_algo_from_pk(const char * algo) pk.len = (size_t) len; pk.data = buf; - /* Use raw decode for hybrid KEMs, DER for others */ - if (IS_HYBRID_KEM(algo)) { - if (kex_get_algo_from_pk_raw(pk, extracted_algo) < 0) { - printf("Failed to extract algo from pk.\n"); - goto fail_pkp; - } - } else { - if (kex_get_algo_from_pk_der(pk, extracted_algo) < 0) { - printf("Failed to extract algo from pk.\n"); - goto fail_pkp; - } + if (kex_get_algo_from_pk_der(pk, extracted_algo) < 0) { + printf("Failed to extract algo from pk.\n"); + goto fail_pkp; } /* All algorithms should now return the specific group name */ @@ -221,6 +213,11 @@ static int test_kex_get_algo_from_pk_all(void) for (i = 0; kex_supported_nids[i] != NID_undef; i++) { const char * algo = kex_nid_to_str(kex_supported_nids[i]); + + /* Raw hybrid PKs are opaque, OAP carries the NID */ + if (IS_HYBRID_KEM(algo)) + continue; + ret |= test_kex_get_algo_from_pk(algo); } diff --git a/src/lib/tests/kex_test_ml_kem.c b/src/lib/tests/kex_test_ml_kem.c index 1f7d7531..7521c5d5 100644 --- a/src/lib/tests/kex_test_ml_kem.c +++ b/src/lib/tests/kex_test_ml_kem.c @@ -220,7 +220,7 @@ static int test_kex_kem(const char * algo) pk.data = buf1; if (IS_HYBRID_KEM(algo)) - ct_len = kex_kem_encap_raw(pk, buf2, kdf, s1); + ct_len = kex_kem_encap_raw(algo, pk, buf2, kdf, s1); else ct_len = kex_kem_encap(pk, buf2, kdf, s1); @@ -285,7 +285,7 @@ static int test_kex_kem_corrupted_ciphertext(const char * algo) pk.data = buf1; if (IS_HYBRID_KEM(algo)) - ct_len = kex_kem_encap_raw(pk, buf2, kdf, s1); + ct_len = kex_kem_encap_raw(algo, pk, buf2, kdf, s1); else ct_len = kex_kem_encap(pk, buf2, kdf, s1); @@ -360,7 +360,7 @@ static int test_kex_kem_wrong_keypair(const char * algo) } if (IS_HYBRID_KEM(algo)) - ct_len = kex_kem_encap_raw(pk1, buf3, NID_sha256, s1); + ct_len = kex_kem_encap_raw(algo, pk1, buf3, NID_sha256, s1); else ct_len = kex_kem_encap(pk1, buf3, NID_sha256, s1); @@ -422,7 +422,7 @@ static int test_kex_kem_truncated_ciphertext(const char * algo) pk.data = buf1; if (IS_HYBRID_KEM(algo)) - ct_len = kex_kem_encap_raw(pk, buf2, NID_sha256, s1); + ct_len = kex_kem_encap_raw(algo, pk, buf2, NID_sha256, s1); else ct_len = kex_kem_encap(pk, buf2, NID_sha256, s1); |
