Clarify thread-safety of key objects.

This often causes confusion since, for various silly reasons (intrinsic
ref-counting, FOO_METHOD, and RSA's cached Montgomery bits), the thread
safety of some functions don't match the usual const/non-const
distinction. Fix const-ness where easy and document it otherwise.

Change-Id: If2037a4874d7580cc79b18ee21f12ae0f47db7fd
Reviewed-on: https://boringssl-review.googlesource.com/31344
Reviewed-by: Ryan Sleevi <rsleevi@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
David Benjamin 2018-08-24 14:58:18 -05:00 committed by CQ bot account: commit-bot@chromium.org
parent e768212e7d
commit 2556f8ba60
7 changed files with 82 additions and 37 deletions

View File

@ -176,7 +176,7 @@ int EVP_PKEY_size(const EVP_PKEY *pkey) {
return 0;
}
int EVP_PKEY_bits(EVP_PKEY *pkey) {
int EVP_PKEY_bits(const EVP_PKEY *pkey) {
if (pkey && pkey->ameth && pkey->ameth->pkey_bits) {
return pkey->ameth->pkey_bits(pkey);
}
@ -225,7 +225,7 @@ int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key) {
return EVP_PKEY_assign(pkey, EVP_PKEY_RSA, key);
}
RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey) {
RSA *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey) {
if (pkey->type != EVP_PKEY_RSA) {
OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_AN_RSA_KEY);
return NULL;
@ -233,7 +233,7 @@ RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey) {
return pkey->pkey.rsa;
}
RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) {
RSA *EVP_PKEY_get1_RSA(const EVP_PKEY *pkey) {
RSA *rsa = EVP_PKEY_get0_RSA(pkey);
if (rsa != NULL) {
RSA_up_ref(rsa);
@ -253,7 +253,7 @@ int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key) {
return EVP_PKEY_assign(pkey, EVP_PKEY_DSA, key);
}
DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey) {
DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey) {
if (pkey->type != EVP_PKEY_DSA) {
OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_DSA_KEY);
return NULL;
@ -261,7 +261,7 @@ DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey) {
return pkey->pkey.dsa;
}
DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) {
DSA *EVP_PKEY_get1_DSA(const EVP_PKEY *pkey) {
DSA *dsa = EVP_PKEY_get0_DSA(pkey);
if (dsa != NULL) {
DSA_up_ref(dsa);
@ -281,7 +281,7 @@ int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) {
return EVP_PKEY_assign(pkey, EVP_PKEY_EC, key);
}
EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) {
EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey) {
if (pkey->type != EVP_PKEY_EC) {
OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_AN_EC_KEY_KEY);
return NULL;
@ -289,7 +289,7 @@ EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) {
return pkey->pkey.ec;
}
EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) {
EC_KEY *EVP_PKEY_get1_EC_KEY(const EVP_PKEY *pkey) {
EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
if (ec_key != NULL) {
EC_KEY_up_ref(ec_key);
@ -297,8 +297,8 @@ EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) {
return ec_key;
}
DH *EVP_PKEY_get0_DH(EVP_PKEY *pkey) { return NULL; }
DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey) { return NULL; }
DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey) { return NULL; }
DH *EVP_PKEY_get1_DH(const EVP_PKEY *pkey) { return NULL; }
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) {
if (!EVP_PKEY_set_type(pkey, type)) {

View File

@ -331,7 +331,7 @@ EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) {
}
}
int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp) {
int i2d_PublicKey(const EVP_PKEY *key, uint8_t **outp) {
switch (key->type) {
case EVP_PKEY_RSA:
return i2d_RSAPublicKey(key->pkey.rsa, outp);

View File

@ -480,7 +480,7 @@ decoding_err:
static const uint8_t kPSSZeroes[] = {0, 0, 0, 0, 0, 0, 0, 0};
int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa, const uint8_t *mHash,
const EVP_MD *Hash, const EVP_MD *mgf1Hash,
const uint8_t *EM, int sLen) {
int i;
@ -579,7 +579,7 @@ err:
return ret;
}
int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
int RSA_padding_add_PKCS1_PSS_mgf1(const RSA *rsa, unsigned char *EM,
const unsigned char *mHash,
const EVP_MD *Hash, const EVP_MD *mgf1Hash,
int sLenRequested) {

View File

@ -85,13 +85,13 @@ err:
return NULL;
}
int RSA_padding_add_PKCS1_PSS(RSA *rsa, uint8_t *EM, const uint8_t *mHash,
int RSA_padding_add_PKCS1_PSS(const RSA *rsa, uint8_t *EM, const uint8_t *mHash,
const EVP_MD *Hash, int sLen) {
return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen);
}
int RSA_verify_PKCS1_PSS(RSA *rsa, const uint8_t *mHash, const EVP_MD *Hash,
const uint8_t *EM, int sLen) {
int RSA_verify_PKCS1_PSS(const RSA *rsa, const uint8_t *mHash,
const EVP_MD *Hash, const uint8_t *EM, int sLen) {
return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen);
}

View File

@ -84,6 +84,12 @@ extern "C" {
// EC key objects.
//
// An |EC_KEY| object represents a public or private EC key. A given object may
// be used concurrently on multiple threads by non-mutating functions, provided
// no other thread is concurrently calling a mutating function. Unless otherwise
// documented, functions which take a |const| pointer are non-mutating and
// functions which take a non-|const| pointer are mutating.
// EC_KEY_new returns a fresh |EC_KEY| object or NULL on error.
OPENSSL_EXPORT EC_KEY *EC_KEY_new(void);
@ -102,7 +108,8 @@ OPENSSL_EXPORT void EC_KEY_free(EC_KEY *key);
// EC_KEY_dup returns a fresh copy of |src| or NULL on error.
OPENSSL_EXPORT EC_KEY *EC_KEY_dup(const EC_KEY *src);
// EC_KEY_up_ref increases the reference count of |key| and returns one.
// EC_KEY_up_ref increases the reference count of |key| and returns one. It does
// not mutate |key| for thread-safety purposes and may be used concurrently.
OPENSSL_EXPORT int EC_KEY_up_ref(EC_KEY *key);
// EC_KEY_is_opaque returns one if |key| is opaque and doesn't expose its key

View File

@ -80,6 +80,12 @@ extern "C" {
// Public key objects.
//
// An |EVP_PKEY| object represents a public or private key. A given object may
// be used concurrently on multiple threads by non-mutating functions, provided
// no other thread is concurrently calling a mutating function. Unless otherwise
// documented, functions which take a |const| pointer are non-mutating and
// functions which take a non-|const| pointer are mutating.
// EVP_PKEY_new creates a new, empty public-key object and returns it or NULL
// on allocation failure.
@ -89,7 +95,9 @@ OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new(void);
// itself.
OPENSSL_EXPORT void EVP_PKEY_free(EVP_PKEY *pkey);
// EVP_PKEY_up_ref increments the reference count of |pkey| and returns one.
// EVP_PKEY_up_ref increments the reference count of |pkey| and returns one. It
// does not mutate |pkey| for thread-safety purposes and may be used
// concurrently.
OPENSSL_EXPORT int EVP_PKEY_up_ref(EVP_PKEY *pkey);
// EVP_PKEY_is_opaque returns one if |pkey| is opaque. Opaque keys are backed by
@ -121,7 +129,7 @@ OPENSSL_EXPORT int EVP_PKEY_size(const EVP_PKEY *pkey);
// EVP_PKEY_bits returns the "size", in bits, of |pkey|. For an RSA key, this
// returns the bit length of the modulus. For an EC key, this returns the bit
// length of the group order.
OPENSSL_EXPORT int EVP_PKEY_bits(EVP_PKEY *pkey);
OPENSSL_EXPORT int EVP_PKEY_bits(const EVP_PKEY *pkey);
// EVP_PKEY_id returns the type of |pkey|, which is one of the |EVP_PKEY_*|
// values.
@ -141,21 +149,26 @@ OPENSSL_EXPORT int EVP_PKEY_type(int nid);
// zero if |key| is NULL. The |get1| functions return a fresh reference to the
// underlying object or NULL if |pkey| is not of the correct type. The |get0|
// functions behave the same but return a non-owning pointer.
//
// The |get0| and |get1| functions take |const| pointers and are thus
// non-mutating for thread-safety purposes, but mutating functions on the
// returned lower-level objects are considered to also mutate the |EVP_PKEY| and
// may not be called concurrently with other operations on the |EVP_PKEY|.
OPENSSL_EXPORT int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key);
OPENSSL_EXPORT int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key);
OPENSSL_EXPORT RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
OPENSSL_EXPORT RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
OPENSSL_EXPORT RSA *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey);
OPENSSL_EXPORT RSA *EVP_PKEY_get1_RSA(const EVP_PKEY *pkey);
OPENSSL_EXPORT int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key);
OPENSSL_EXPORT int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key);
OPENSSL_EXPORT DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey);
OPENSSL_EXPORT DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
OPENSSL_EXPORT DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey);
OPENSSL_EXPORT DSA *EVP_PKEY_get1_DSA(const EVP_PKEY *pkey);
OPENSSL_EXPORT int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key);
OPENSSL_EXPORT int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key);
OPENSSL_EXPORT EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey);
OPENSSL_EXPORT EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
OPENSSL_EXPORT EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey);
OPENSSL_EXPORT EC_KEY *EVP_PKEY_get1_EC_KEY(const EVP_PKEY *pkey);
// EVP_PKEY_new_ed25519_public returns a newly allocated |EVP_PKEY| wrapping an
// Ed25519 public key, or NULL on allocation error.
@ -240,6 +253,9 @@ OPENSSL_EXPORT int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key);
// Ed25519, |type| should be NULL. The |EVP_MD_CTX| itself is unused but is
// present so the API is uniform. See |EVP_DigestSign|.
//
// This function does not mutate |pkey| for thread-safety purposes and may be
// used concurrently with other non-mutating functions on |pkey|.
//
// It returns one on success, or zero on error.
OPENSSL_EXPORT int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e,
@ -293,6 +309,9 @@ OPENSSL_EXPORT int EVP_DigestSign(EVP_MD_CTX *ctx, uint8_t *out_sig,
// Ed25519, |type| should be NULL. The |EVP_MD_CTX| itself is unused but is
// present so the API is uniform. See |EVP_DigestVerify|.
//
// This function does not mutate |pkey| for thread-safety purposes and may be
// used concurrently with other non-mutating functions on |pkey|.
//
// It returns one on success, or zero on error.
OPENSSL_EXPORT int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e,
@ -353,7 +372,9 @@ OPENSSL_EXPORT int EVP_SignUpdate(EVP_MD_CTX *ctx, const void *data,
// It returns one on success and zero otherwise.
//
// It does not modify |ctx|, thus it's possible to continue to use |ctx| in
// order to sign a longer message.
// order to sign a longer message. It also does not mutate |pkey| for
// thread-safety purposes and may be used concurrently with other non-mutating
// functions on |pkey|.
OPENSSL_EXPORT int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig,
unsigned int *out_sig_len, EVP_PKEY *pkey);
@ -386,7 +407,9 @@ OPENSSL_EXPORT int EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *data,
// It returns one on success and zero otherwise.
//
// It does not modify |ctx|, thus it's possible to continue to use |ctx| in
// order to sign a longer message.
// order to verify a longer message. It also does not mutate |pkey| for
// thread-safety purposes and may be used concurrently with other non-mutating
// functions on |pkey|.
OPENSSL_EXPORT int EVP_VerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
size_t sig_len, EVP_PKEY *pkey);
@ -779,7 +802,7 @@ OPENSSL_EXPORT int i2d_PrivateKey(const EVP_PKEY *key, uint8_t **outp);
// EC keys are serialized as an EC point per SEC 1.
//
// Use |RSA_marshal_public_key| or |EC_POINT_point2cbb| instead.
OPENSSL_EXPORT int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp);
OPENSSL_EXPORT int i2d_PublicKey(const EVP_PKEY *key, uint8_t **outp);
// d2i_PrivateKey parses an ASN.1, DER-encoded, private key from |len| bytes at
// |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
@ -804,10 +827,10 @@ OPENSSL_EXPORT EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp,
long len);
// EVP_PKEY_get0_DH returns NULL.
OPENSSL_EXPORT DH *EVP_PKEY_get0_DH(EVP_PKEY *pkey);
OPENSSL_EXPORT DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey);
// EVP_PKEY_get1_DH returns NULL.
OPENSSL_EXPORT DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
OPENSSL_EXPORT DH *EVP_PKEY_get1_DH(const EVP_PKEY *pkey);
// Preprocessor compatibility section (hidden).

View File

@ -72,8 +72,14 @@ extern "C" {
// Allocation and destruction.
//
// An |RSA| object represents a public or private RSA key. A given object may be
// used concurrently on multiple threads by non-mutating functions, provided no
// other thread is concurrently calling a mutating function. Unless otherwise
// documented, functions which take a |const| pointer are non-mutating and
// functions which take a non-|const| pointer are mutating.
// RSA_new returns a new, empty RSA object or NULL on error.
// RSA_new returns a new, empty |RSA| object or NULL on error.
OPENSSL_EXPORT RSA *RSA_new(void);
// RSA_new_method acts the same as |RSA_new| but takes an explicit |ENGINE|.
@ -83,7 +89,8 @@ OPENSSL_EXPORT RSA *RSA_new_method(const ENGINE *engine);
// reference count drops to zero.
OPENSSL_EXPORT void RSA_free(RSA *rsa);
// RSA_up_ref increments the reference count of |rsa| and returns one.
// RSA_up_ref increments the reference count of |rsa| and returns one. It does
// not mutate |rsa| for thread-safety purposes and may be used concurrently.
OPENSSL_EXPORT int RSA_up_ref(RSA *rsa);
@ -164,6 +171,9 @@ OPENSSL_EXPORT int RSA_generate_key_fips(RSA *rsa, int bits, BN_GENCB *cb);
// Encryption / Decryption
//
// These functions are considered non-mutating for thread-safety purposes and
// may be used concurrently.
// Padding types for encryption.
#define RSA_PKCS1_PADDING 1
@ -231,6 +241,9 @@ OPENSSL_EXPORT int RSA_private_decrypt(size_t flen, const uint8_t *from,
// Signing / Verification
//
// These functions are considered non-mutating for thread-safety purposes and
// may be used concurrently.
// RSA_sign signs |in_len| bytes of digest from |in| with |rsa| using
// RSASSA-PKCS1-v1_5. It writes, at most, |RSA_size(rsa)| bytes to |out|. On
@ -372,8 +385,9 @@ OPENSSL_EXPORT RSA *RSAPrivateKey_dup(const RSA *rsa);
// returns zero then a more detailed error is available on the error queue.
OPENSSL_EXPORT int RSA_check_key(const RSA *rsa);
// RSA_check_fips performs public key validity tests on |key|. It returns one
// if they pass and zero otherwise. Opaque keys always fail.
// RSA_check_fips performs public key validity tests on |key|. It returns one if
// they pass and zero otherwise. Opaque keys always fail. This function does not
// mutate |rsa| for thread-safety purposes and may be used concurrently.
OPENSSL_EXPORT int RSA_check_fips(RSA *key);
// RSA_verify_PKCS1_PSS_mgf1 verifies that |EM| is a correct PSS padding of
@ -390,7 +404,8 @@ OPENSSL_EXPORT int RSA_check_fips(RSA *key);
//
// This function implements only the low-level padding logic. Use
// |RSA_verify_pss_mgf1| instead.
OPENSSL_EXPORT int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
OPENSSL_EXPORT int RSA_verify_PKCS1_PSS_mgf1(const RSA *rsa,
const uint8_t *mHash,
const EVP_MD *Hash,
const EVP_MD *mgf1Hash,
const uint8_t *EM, int sLen);
@ -407,7 +422,7 @@ OPENSSL_EXPORT int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
//
// This function implements only the low-level padding logic. Use
// |RSA_sign_pss_mgf1| instead.
OPENSSL_EXPORT int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, uint8_t *EM,
OPENSSL_EXPORT int RSA_padding_add_PKCS1_PSS_mgf1(const RSA *rsa, uint8_t *EM,
const uint8_t *mHash,
const EVP_MD *Hash,
const EVP_MD *mgf1Hash,
@ -567,7 +582,7 @@ OPENSSL_EXPORT int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp);
//
// This function implements only the low-level padding logic. Use
// |RSA_sign_pss_mgf1| instead.
OPENSSL_EXPORT int RSA_padding_add_PKCS1_PSS(RSA *rsa, uint8_t *EM,
OPENSSL_EXPORT int RSA_padding_add_PKCS1_PSS(const RSA *rsa, uint8_t *EM,
const uint8_t *mHash,
const EVP_MD *Hash, int sLen);
@ -576,7 +591,7 @@ OPENSSL_EXPORT int RSA_padding_add_PKCS1_PSS(RSA *rsa, uint8_t *EM,
//
// This function implements only the low-level padding logic. Use
// |RSA_verify_pss_mgf1| instead.
OPENSSL_EXPORT int RSA_verify_PKCS1_PSS(RSA *rsa, const uint8_t *mHash,
OPENSSL_EXPORT int RSA_verify_PKCS1_PSS(const RSA *rsa, const uint8_t *mHash,
const EVP_MD *Hash, const uint8_t *EM,
int sLen);