Skip to content

Commit

Permalink
Merge branch 'main' into x86-sse2-flag
Browse files Browse the repository at this point in the history
  • Loading branch information
graebm authored Sep 12, 2024
2 parents b8942d5 + 3c22151 commit 966232e
Show file tree
Hide file tree
Showing 42 changed files with 2,560 additions and 639 deletions.
63 changes: 45 additions & 18 deletions crypto/ec_extra/ec_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@
#include <limits.h>
#include <string.h>

#include <openssl/bytestring.h>
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/nid.h>
Expand All @@ -76,19 +77,15 @@ static const CBS_ASN1_TAG kPublicKeyTag =
// acceptable groups, so parsers don't have to pull in all four.
typedef const EC_GROUP *(*ec_group_func)(void);
static const ec_group_func kAllGroups[] = {
&EC_group_p224,
&EC_group_p256,
&EC_group_p384,
&EC_group_p521,
&EC_group_secp256k1,
&EC_group_p224, &EC_group_p256, &EC_group_p384,
&EC_group_p521, &EC_group_secp256k1,
};

EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) {
CBS ec_private_key, private_key;
uint64_t version;
if (!CBS_get_asn1(cbs, &ec_private_key, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1_uint64(&ec_private_key, &version) ||
version != 1 ||
!CBS_get_asn1_uint64(&ec_private_key, &version) || version != 1 ||
!CBS_get_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING)) {
OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
return NULL;
Expand Down Expand Up @@ -151,8 +148,7 @@ EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) {
!CBS_get_asn1(&child, &public_key, CBS_ASN1_BITSTRING) ||
// As in a SubjectPublicKeyInfo, the byte-encoded public key is then
// encoded as a BIT STRING with bits ordered as in the DER encoding.
!CBS_get_u8(&public_key, &padding) ||
padding != 0 ||
!CBS_get_u8(&public_key, &padding) || padding != 0 ||
// Explicitly check |public_key| is non-empty to save the conversion
// form later.
CBS_len(&public_key) == 0 ||
Expand Down Expand Up @@ -264,16 +260,14 @@ static int parse_explicit_prime_curve(CBS *in,
int has_cofactor;
uint64_t version;
if (!CBS_get_asn1(in, &params, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1_uint64(&params, &version) ||
version != 1 ||
!CBS_get_asn1_uint64(&params, &version) || version != 1 ||
!CBS_get_asn1(&params, &field_id, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&field_id, &field_type, CBS_ASN1_OBJECT) ||
CBS_len(&field_type) != sizeof(kPrimeField) ||
OPENSSL_memcmp(CBS_data(&field_type), kPrimeField, sizeof(kPrimeField)) !=
0 ||
!CBS_get_asn1(&field_id, &out->prime, CBS_ASN1_INTEGER) ||
!CBS_is_unsigned_asn1_integer(&out->prime) ||
CBS_len(&field_id) != 0 ||
!CBS_is_unsigned_asn1_integer(&out->prime) || CBS_len(&field_id) != 0 ||
!CBS_get_asn1(&params, &curve, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&curve, &out->a, CBS_ASN1_OCTETSTRING) ||
!CBS_get_asn1(&curve, &out->b, CBS_ASN1_OCTETSTRING) ||
Expand All @@ -292,8 +286,7 @@ static int parse_explicit_prime_curve(CBS *in,

if (has_cofactor) {
// We only support prime-order curves so the cofactor must be one.
if (CBS_len(&cofactor) != 1 ||
CBS_data(&cofactor)[0] != 1) {
if (CBS_len(&cofactor) != 1 || CBS_data(&cofactor)[0] != 1) {
OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
return 0;
}
Expand Down Expand Up @@ -546,6 +539,40 @@ int i2d_ECPKParameters(const EC_GROUP *group, uint8_t **outp) {
return CBB_finish_i2d(&cbb, outp);
}

EC_GROUP *d2i_ECPKParameters_bio(BIO *bio, EC_GROUP **out_group) {
if (bio == NULL) {
OPENSSL_PUT_ERROR(PKCS7, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}

uint8_t *data;
size_t len;
if (!BIO_read_asn1(bio, &data, &len, INT_MAX)) {
return NULL;
}
const uint8_t *ptr = data;
EC_GROUP *ret = d2i_ECPKParameters(out_group, &ptr, len);
OPENSSL_free(data);
return ret;
}

int i2d_ECPKParameters_bio(BIO *bio, const EC_GROUP *group) {
if (bio == NULL || group == NULL) {
OPENSSL_PUT_ERROR(PKCS7, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}

uint8_t *out = NULL;
int len = i2d_ECPKParameters(group, &out);
if (out == NULL) {
return 0;
}

int ret = BIO_write_all(bio, out, len);
OPENSSL_free(out);
return ret;
}

EC_KEY *o2i_ECPublicKey(EC_KEY **keyp, const uint8_t **inp, long len) {
EC_KEY *ret = NULL;

Expand Down Expand Up @@ -599,8 +626,8 @@ size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
}

static size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point,
point_conversion_form_t form,
uint8_t **pbuf, BN_CTX *ctx) {
point_conversion_form_t form, uint8_t **pbuf,
BN_CTX *ctx) {
size_t len;
uint8_t *buf;

Expand Down
37 changes: 35 additions & 2 deletions crypto/fipsmodule/curve25519/curve25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ void ed25519_sha512(uint8_t out[SHA512_DIGEST_LENGTH],
void ED25519_keypair_from_seed(uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN],
uint8_t out_private_key[ED25519_PRIVATE_KEY_LEN],
const uint8_t seed[ED25519_SEED_LEN]) {
// ED25519_keypair already ensures this with the same check, and is also the
// function that is approved for FIPS (sets the indicator). Ensuring it here
// for brevity.
boringssl_ensure_eddsa_self_test();

// Step: rfc8032 5.1.5.1
// Compute SHA512(seed).
Expand Down Expand Up @@ -101,6 +105,7 @@ void ED25519_keypair_from_seed(uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN],

void ED25519_keypair(uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN],
uint8_t out_private_key[ED25519_PRIVATE_KEY_LEN]) {
boringssl_ensure_eddsa_self_test();
SET_DIT_AUTO_DISABLE;

// Ed25519 key generation: rfc8032 5.1.5
Expand All @@ -112,11 +117,20 @@ void ED25519_keypair(uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN],
// description why this is useful.
ED25519_keypair_from_seed(out_public_key, out_private_key, seed);
OPENSSL_cleanse(seed, ED25519_SEED_LEN);

FIPS_service_indicator_update_state();
}

int ED25519_sign(uint8_t out_sig[ED25519_SIGNATURE_LEN],
const uint8_t *message, size_t message_len,
const uint8_t private_key[ED25519_PRIVATE_KEY_LEN]) {
boringssl_ensure_eddsa_self_test();
return ED25519_sign_no_self_test(out_sig, message, message_len, private_key);
}

int ED25519_sign_no_self_test(uint8_t out_sig[ED25519_SIGNATURE_LEN],
const uint8_t *message, size_t message_len,
const uint8_t private_key[ED25519_PRIVATE_KEY_LEN]) {
// NOTE: The documentation on this function says that it returns zero on
// allocation failure. While that can't happen with the current
// implementation, we want to reserve the ability to allocate in this
Expand Down Expand Up @@ -155,13 +169,21 @@ int ED25519_sign(uint8_t out_sig[ED25519_SIGNATURE_LEN],

// The signature is computed from the private key, but is public.
CONSTTIME_DECLASSIFY(out_sig, 64);

FIPS_service_indicator_update_state();
return 1;
}

int ED25519_verify(const uint8_t *message, size_t message_len,
const uint8_t signature[ED25519_SIGNATURE_LEN],
const uint8_t public_key[ED25519_PUBLIC_KEY_LEN]) {
boringssl_ensure_eddsa_self_test();
return ED25519_verify_no_self_test(message, message_len, signature, public_key);
}

int ED25519_verify_no_self_test(const uint8_t *message, size_t message_len,
const uint8_t signature[ED25519_SIGNATURE_LEN],
const uint8_t public_key[ED25519_PUBLIC_KEY_LEN]) {
// Ed25519 verify: rfc8032 5.1.7

// Step: rfc8032 5.1.7.1 (up to decoding the public key)
Expand Down Expand Up @@ -212,10 +234,21 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
#endif

// Comparison [S]B - [k]A' =? R_expected. Short-circuits if decoding failed.
return (res == 1) &&
CRYPTO_memcmp(R_computed_encoded, R_expected, sizeof(R_computed_encoded)) == 0;
res = (res == 1) && CRYPTO_memcmp(R_computed_encoded, R_expected,
sizeof(R_computed_encoded)) == 0;
if(res) {
FIPS_service_indicator_update_state();
}
return res;
}

int ED25519_check_public_key(const uint8_t public_key[ED25519_PUBLIC_KEY_LEN]) {
#if defined(CURVE25519_S2N_BIGNUM_CAPABLE)
return ed25519_check_public_key_s2n_bignum(public_key);
#else
return ed25519_check_public_key_nohw(public_key);
#endif
}

void X25519_public_from_private(
uint8_t out_public_value[X25519_PUBLIC_VALUE_LEN],
Expand Down
8 changes: 8 additions & 0 deletions crypto/fipsmodule/curve25519/curve25519_nohw.c
Original file line number Diff line number Diff line change
Expand Up @@ -2043,3 +2043,11 @@ int ed25519_verify_nohw(uint8_t R_computed_encoded[32],

return 1;
}

int ed25519_check_public_key_nohw(const uint8_t public_key[ED25519_PUBLIC_KEY_LEN]) {
ge_p3 A;
if (!x25519_ge_frombytes_vartime(&A, public_key)) {
return 0;
}
return 1;
}
8 changes: 8 additions & 0 deletions crypto/fipsmodule/curve25519/curve25519_s2n_bignum_asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,12 @@ int ed25519_verify_s2n_bignum(uint8_t R_computed_encoded[32],
return 1;
}

int ed25519_check_public_key_s2n_bignum(const uint8_t public_key[ED25519_PUBLIC_KEY_LEN]) {
uint64_t A[8] = {0};
if (edwards25519_decode_selector(A, public_key) != 0) {
return 0;
}
return 1;
}

#endif
13 changes: 13 additions & 0 deletions crypto/fipsmodule/curve25519/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ extern "C" {

#include "../../internal.h"

int ED25519_sign_no_self_test(uint8_t out_sig[ED25519_SIGNATURE_LEN],
const uint8_t *message, size_t message_len,
const uint8_t private_key[ED25519_PRIVATE_KEY_LEN]);

int ED25519_verify_no_self_test(const uint8_t *message, size_t message_len,
const uint8_t signature[ED25519_SIGNATURE_LEN],
const uint8_t public_key[ED25519_PUBLIC_KEY_LEN]);

// If (1) x86_64 or aarch64, (2) linux or apple, and (3) OPENSSL_NO_ASM is not
// set, s2n-bignum path is capable.
#if ((defined(OPENSSL_X86_64) && !defined(MY_ASSEMBLER_IS_TOO_OLD_FOR_512AVX)) || \
Expand Down Expand Up @@ -185,6 +193,11 @@ void ed25519_sha512(uint8_t out[SHA512_DIGEST_LENGTH],
const void *input1, size_t len1, const void *input2, size_t len2,
const void *input3, size_t len3);


int ed25519_check_public_key_s2n_bignum(const uint8_t public_key[ED25519_PUBLIC_KEY_LEN]);
int ed25519_check_public_key_nohw(const uint8_t public_key[ED25519_PUBLIC_KEY_LEN]);
OPENSSL_EXPORT int ED25519_check_public_key(const uint8_t public_key[ED25519_PUBLIC_KEY_LEN]);

#if defined(__cplusplus)
} // extern C
#endif
Expand Down
9 changes: 9 additions & 0 deletions crypto/fipsmodule/ec/ec_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2551,3 +2551,12 @@ TEST(ECTest, ECEngine) {
EC_KEY_METHOD_free(eng_funcs);
}

TEST(ECTest, ECPKParmatersBio) {
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));

EXPECT_TRUE(i2d_ECPKParameters_bio(bio.get(), EC_group_p256()));
EXPECT_EQ(d2i_ECPKParameters_bio(bio.get(), nullptr), EC_group_p256());

EXPECT_TRUE(i2d_ECPKParameters_bio(bio.get(), EC_group_secp256k1()));
EXPECT_EQ(d2i_ECPKParameters_bio(bio.get(), nullptr), EC_group_secp256k1());
}
5 changes: 4 additions & 1 deletion crypto/fipsmodule/ec/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,10 @@ struct ec_key_st {

// d2i_ECPKParameters deserializes the |ECPKParameters| specified in RFC 3279
// to an |EC_GROUP| from |inp|. Only deserialization of namedCurves or
// explicitly-encoded versions of namedCurves are supported.
// explicitly-encoded versions of namedCurves are supported. If |*out_group| is
// non-null, the original |*out_group| is freed and the returned |EC_GROUP| is
// also written to |*out_group|. The user continues to maintain the memory
// assigned to |*out_group| if non-null.
EC_GROUP *d2i_ECPKParameters(EC_GROUP **out_group, const uint8_t **inp,
long len);

Expand Down
4 changes: 3 additions & 1 deletion crypto/fipsmodule/evp/digestsign.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,9 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, uint8_t *out_sig, size_t *out_sig_len,
data_len);
end:
FIPS_service_indicator_unlock_state();
if (ret > 0) {
if (ret > 0 && out_sig != NULL) {
// Indicator should only be set if we performed crypto, don't set if we only
// performed a size check.
EVP_DigestSign_verify_service_indicator(ctx);
}
return ret;
Expand Down
54 changes: 40 additions & 14 deletions crypto/fipsmodule/evp/evp_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -591,30 +591,56 @@ int EVP_PKEY_encapsulate_deterministic(EVP_PKEY_CTX *ctx,
seed, seed_len);
}

int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx,
uint8_t *ciphertext, size_t *ciphertext_len,
uint8_t *shared_secret, size_t *shared_secret_len) {
int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx, uint8_t *ciphertext,
size_t *ciphertext_len, uint8_t *shared_secret,
size_t *shared_secret_len) {
// We have to avoid potential underlying services updating the indicator
// state, so we lock the state here.
FIPS_service_indicator_lock_state();
SET_DIT_AUTO_DISABLE;
int ret = 0;
if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->encapsulate == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
goto end;
}

return ctx->pmeth->encapsulate(ctx, ciphertext, ciphertext_len,
shared_secret, shared_secret_len);
if (!ctx->pmeth->encapsulate(ctx, ciphertext, ciphertext_len, shared_secret,
shared_secret_len)) {
goto end;
}
ret = 1;
end:
FIPS_service_indicator_unlock_state();
if (ret && ciphertext != NULL && shared_secret != NULL) {
EVP_PKEY_encapsulate_verify_service_indicator(ctx);
}
return ret;
}

int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx,
uint8_t *shared_secret, size_t *shared_secret_len,
const uint8_t *ciphertext, size_t ciphertext_len) {
int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx, uint8_t *shared_secret,
size_t *shared_secret_len, const uint8_t *ciphertext,
size_t ciphertext_len) {
// We have to avoid potential underlying services updating the indicator
// state, so we lock the state here.
FIPS_service_indicator_lock_state();
SET_DIT_AUTO_DISABLE;
int ret = 0;
if (ctx == NULL || ctx->pmeth == NULL || ctx->pmeth->decapsulate == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
goto end;
}

return ctx->pmeth->decapsulate(ctx, shared_secret, shared_secret_len,
ciphertext, ciphertext_len);
if (!ctx->pmeth->decapsulate(ctx, shared_secret, shared_secret_len,
ciphertext, ciphertext_len)) {
goto end;
}
ret = 1;
end:
FIPS_service_indicator_unlock_state();
if (ret && shared_secret != NULL) {
EVP_PKEY_decapsulate_verify_service_indicator(ctx);
}
return ret;
}

// Deprecated keygen NO-OP functions
Expand Down
3 changes: 2 additions & 1 deletion crypto/fipsmodule/evp/p_kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,11 @@ static int pkey_kem_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
if (key == NULL ||
!KEM_KEY_init(key, kem) ||
!kem->method->keygen(key->public_key, key->secret_key) ||
!EVP_PKEY_assign(pkey, EVP_PKEY_KEM, key)) {
!EVP_PKEY_set_type(pkey, EVP_PKEY_KEM)) {
KEM_KEY_free(key);
return 0;
}
pkey->pkey.kem_key = key;

return 1;
}
Expand Down
Loading

0 comments on commit 966232e

Please sign in to comment.