size_t enc_len = params->sk_len;
const POLY *t0 = key->t0.poly;
WPACKET pkt;
- uint8_t *enc = OPENSSL_malloc(enc_len);
+ uint8_t *enc = OPENSSL_secure_malloc(enc_len);
if (enc == NULL)
return 0;
if (!WPACKET_get_total_written(&pkt, &written)
|| written != enc_len)
goto err;
- OPENSSL_clear_free(key->priv_encoding, enc_len);
+ OPENSSL_secure_clear_free(key->priv_encoding, enc_len);
key->priv_encoding = enc;
ret = 1;
err:
goto err;
if (PACKET_remaining(&pkt) != 0)
goto err;
- if (key->priv_encoding == NULL
- && (key->priv_encoding = OPENSSL_memdup(in, in_len)) == NULL)
- goto err;
+ if (key->priv_encoding == NULL) {
+ key->priv_encoding = OPENSSL_secure_malloc(in_len);
+ if (key->priv_encoding == NULL)
+ goto err;
+ memcpy(key->priv_encoding, in, in_len);
+ }
/*
* Computing the public key also computes its hash, which must be equal to
* the |tr| value in the private key, else the key was corrupted.
|| key->seed != NULL)
return 0;
- if (sk != NULL
- && (key->priv_encoding = OPENSSL_memdup(sk, sk_len)) == NULL)
- goto end;
+ if (sk != NULL) {
+ key->priv_encoding = OPENSSL_secure_malloc(sk_len);
+ if (key->priv_encoding == NULL)
+ goto end;
+ memcpy(key->priv_encoding, sk, sk_len);
+ }
+
if (seed != NULL
&& (key->seed = OPENSSL_memdup(seed, seed_len)) == NULL)
goto end;
end:
if (!ret) {
- OPENSSL_free(key->priv_encoding);
+ OPENSSL_secure_free(key->priv_encoding);
OPENSSL_free(key->seed);
key->priv_encoding = key->seed = NULL;
}
if (key->s1.poly != NULL)
return 0;
- if (!vector_alloc(&key->s1, l + 2 * k))
+ if (!vector_secure_alloc(&key->s1, l + 2 * k))
return 0;
poly = key->s1.poly;
vector_zero(&key->s1);
vector_zero(&key->s2);
vector_zero(&key->t0);
- vector_free(&key->s1);
+ vector_secure_free(&key->s1);
key->s2.poly = NULL;
key->t0.poly = NULL;
}
OPENSSL_free(key->pub_encoding);
key->pub_encoding = NULL;
if (key->priv_encoding != NULL)
- OPENSSL_clear_free(key->priv_encoding, key->params->sk_len);
+ OPENSSL_secure_clear_free(key->priv_encoding, key->params->sk_len);
key->priv_encoding = NULL;
if (key->seed != NULL)
OPENSSL_clear_free(key->seed, ML_DSA_SEED_BYTES);
vector_copy(&ret->s2, &src->s2);
vector_copy(&ret->t0, &src->t0);
}
- if ((ret->priv_encoding =
- OPENSSL_memdup(src->priv_encoding,
- src->params->sk_len)) == NULL)
+ ret->priv_encoding = OPENSSL_secure_malloc(src->params->sk_len);
+ if (!ret->priv_encoding)
goto err;
+ memcpy(ret->priv_encoding, src->priv_encoding, src->params->sk_len);
}
if (src->seed != NULL
&& (ret->seed = OPENSSL_memdup(src->seed,
return 1;
}
+static ossl_inline ossl_unused
+int vector_secure_alloc(VECTOR *v, size_t num_polys)
+{
+ v->poly = OPENSSL_secure_malloc(num_polys * sizeof(POLY));
+ if (v->poly == NULL)
+ return 0;
+ v->num_poly = num_polys;
+ return 1;
+}
+
static ossl_inline ossl_unused
void vector_free(VECTOR *v)
{
v->num_poly = 0;
}
+static ossl_inline ossl_unused
+void vector_secure_free(VECTOR *v)
+{
+ OPENSSL_secure_clear_free(v->poly, v->num_poly * sizeof(POLY));
+ v->poly = NULL;
+ v->num_poly = 0;
+}
+
/* @brief zeroize a vectors polynomial coefficients */
static ossl_inline ossl_unused
void vector_zero(VECTOR *va)
* secret |z|, and seed |d|, we can cleanse all three in one call.
*
* - Otherwise, when key->d is set, cleanse the stashed seed.
+ *
+ * If the memory has been allocated with secure memory, it will be cleared
+ * before being free'd under the OPENSSL_secure_free call.
*/
- if (ossl_ml_kem_have_prvkey(key))
- OPENSSL_cleanse(key->s,
- key->vinfo->rank * sizeof(scalar) + 2 * ML_KEM_RANDOM_BYTES);
- OPENSSL_free(key->t);
+ if (ossl_ml_kem_have_prvkey(key)) {
+ if (!CRYPTO_secure_allocated(key->t))
+ OPENSSL_cleanse(key->s, key->vinfo->rank * sizeof(scalar) + 2 * ML_KEM_RANDOM_BYTES);
+ OPENSSL_secure_free(key->t);
+ } else {
+ OPENSSL_free(key->t);
+ }
+
key->d = key->z = (uint8_t *)(key->s = key->m = key->t = NULL);
}
{
int ok = 0;
ML_KEM_KEY *ret;
+ void *tmp;
/*
* Partially decoded keys, not yet imported or loaded, should never be
ret->pkhash = ret->rho + ML_KEM_RANDOM_BYTES;
break;
case OSSL_KEYMGMT_SELECT_PRIVATE_KEY:
- ok = add_storage(OPENSSL_memdup(key->t, key->vinfo->prvalloc), 1, ret);
+ tmp = OPENSSL_secure_malloc(key->vinfo->prvalloc);
+ if (tmp == NULL)
+ break;
+ memcpy(tmp, key->t, key->vinfo->prvalloc);
+ ok = add_storage(tmp, 1, ret);
/* Duplicated keys retain |d|, if available */
if (key->d != NULL)
ret->d = ret->z + ML_KEM_RANDOM_BYTES;
if (ossl_ml_kem_decoded_key(key)) {
OPENSSL_cleanse(key->seedbuf, sizeof(key->seedbuf));
- if (ossl_ml_kem_have_dkenc(key)) {
- OPENSSL_cleanse(key->encoded_dk, key->vinfo->prvkey_bytes);
- OPENSSL_free(key->encoded_dk);
- }
+ if (ossl_ml_kem_have_dkenc(key))
+ OPENSSL_secure_clear_free(key->encoded_dk, key->vinfo->prvkey_bytes);
}
ossl_ml_kem_key_reset(key);
OPENSSL_free(key);
|| (mdctx = EVP_MD_CTX_new()) == NULL)
return 0;
- if (add_storage(OPENSSL_malloc(vinfo->prvalloc), 1, key))
+ if (add_storage(OPENSSL_secure_malloc(vinfo->prvalloc), 1, key))
ret = parse_prvkey(in, mdctx, key);
if (!ret)
*/
CONSTTIME_SECRET(seed, ML_KEM_SEED_BYTES);
- if (add_storage(OPENSSL_malloc(vinfo->prvalloc), 1, key))
+ if (add_storage(OPENSSL_secure_malloc(vinfo->prvalloc), 1, key))
ret = genkey(seed, mdctx, pubenc, key);
OPENSSL_cleanse(seed, sizeof(seed));
}
}
if (p8fmt->priv_length > 0) {
- if ((key->encoded_dk = OPENSSL_malloc(p8fmt->priv_length)) == NULL) {
+ if ((key->encoded_dk = OPENSSL_secure_malloc(p8fmt->priv_length)) == NULL) {
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY,
"error parsing %s private key",
v->algorithm_name);
if (!ml_kem_pairwise_test(key, key->prov_flags))
goto err;
}
- OPENSSL_free(encoded_dk);
+ OPENSSL_secure_clear_free(encoded_dk, key->vinfo->prvkey_bytes);
return key;
}
err:
- OPENSSL_free(encoded_dk);
+ OPENSSL_secure_clear_free(encoded_dk, key->vinfo->prvkey_bytes);
ossl_ml_kem_key_free(key);
return NULL;
}