Add some Node compatibility functions.
This doesn't cover all the functions used by Node, but it's the easy
bits. (EVP_PKEY_paramgen will be done separately as its a non-trivial
bit of machinery.)
Change-Id: I6501e99f9239ffcdcc57b961ebe85d0ad3965549
Reviewed-on: https://boringssl-review.googlesource.com/c/34544
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
diff --git a/crypto/bn_extra/convert.c b/crypto/bn_extra/convert.c
index 9a1a69e..6e930fc 100644
--- a/crypto/bn_extra/convert.c
+++ b/crypto/bn_extra/convert.c
@@ -460,3 +460,11 @@
}
return out;
}
+
+int BN_bn2binpad(const BIGNUM *in, uint8_t *out, int len) {
+ if (len < 0 ||
+ !BN_bn2bin_padded(out, (size_t)len, in)) {
+ return -1;
+ }
+ return len;
+}
diff --git a/crypto/evp/evp_asn1.c b/crypto/evp/evp_asn1.c
index 383e2f9..d56b93b 100644
--- a/crypto/evp/evp_asn1.c
+++ b/crypto/evp/evp_asn1.c
@@ -344,3 +344,44 @@
return -1;
}
}
+
+EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **out, const uint8_t **inp,
+ long len) {
+ EVP_PKEY *ret = EVP_PKEY_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ CBS cbs;
+ CBS_init(&cbs, *inp, len < 0 ? 0 : (size_t)len);
+ switch (type) {
+ case EVP_PKEY_RSA: {
+ RSA *rsa = RSA_parse_public_key(&cbs);
+ if (rsa == NULL || !EVP_PKEY_assign_RSA(ret, rsa)) {
+ RSA_free(rsa);
+ goto err;
+ }
+ break;
+ }
+
+ // Unlike OpenSSL, we do not support EC keys with this API. The raw EC
+ // public key serialization requires knowing the group. In OpenSSL, calling
+ // this function with |EVP_PKEY_EC| and setting |out| to NULL does not work.
+ // It requires |*out| to include a partially-initiazed |EVP_PKEY| to extract
+ // the group.
+ default:
+ OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ goto err;
+ }
+
+ *inp = CBS_data(&cbs);
+ if (out != NULL) {
+ EVP_PKEY_free(*out);
+ *out = ret;
+ }
+ return ret;
+
+err:
+ EVP_PKEY_free(ret);
+ return NULL;
+}
diff --git a/crypto/fipsmodule/ec/ec.c b/crypto/fipsmodule/ec/ec.c
index 90b9d71..4ea5529 100644
--- a/crypto/fipsmodule/ec/ec.c
+++ b/crypto/fipsmodule/ec/ec.c
@@ -660,6 +660,22 @@
return NULL;
}
+int EC_curve_nist2nid(const char *name) {
+ if (strcmp(name, "P-224") == 0) {
+ return NID_secp224r1;
+ }
+ if (strcmp(name, "P-256") == 0) {
+ return NID_X9_62_prime256v1;
+ }
+ if (strcmp(name, "P-384") == 0) {
+ return NID_secp384r1;
+ }
+ if (strcmp(name, "P-521") == 0) {
+ return NID_secp521r1;
+ }
+ return NID_undef;
+}
+
EC_POINT *EC_POINT_new(const EC_GROUP *group) {
if (group == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
diff --git a/include/openssl/bn.h b/include/openssl/bn.h
index c198f4d..b6b7e9ab 100644
--- a/include/openssl/bn.h
+++ b/include/openssl/bn.h
@@ -932,6 +932,12 @@
OPENSSL_EXPORT int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod,
BN_CTX *ctx);
+// BN_bn2binpad behaves like |BN_bn2bin_padded|, but it returns |len| on success
+// and -1 on error.
+//
+// Use |BN_bn2bin_padded| instead. It is |size_t|-clean.
+OPENSSL_EXPORT int BN_bn2binpad(const BIGNUM *in, uint8_t *out, int len);
+
// Private functions
diff --git a/include/openssl/ec.h b/include/openssl/ec.h
index c65a1a7..16dadf2 100644
--- a/include/openssl/ec.h
+++ b/include/openssl/ec.h
@@ -162,6 +162,11 @@
// for |NID_X9_62_prime256v1|.
OPENSSL_EXPORT const char *EC_curve_nid2nist(int nid);
+// EC_curve_nist2nid returns the NID of the elliptic curve specified by the NIST
+// name |name|, or |NID_undef| if |name| is not a recognized name. For example,
+// it returns |NID_X9_62_prime256v1| for "P-256".
+OPENSSL_EXPORT int EC_curve_nist2nid(const char *name);
+
// Points on elliptic curves.
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 1d7192d..cbe93d8 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -826,6 +826,20 @@
OPENSSL_EXPORT EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp,
long len);
+// d2i_PublicKey parse a public key from |len| bytes at |*inp| in a type-
+// specific format specified by |type|. If |out| is not NULL then, on exit, a
+// pointer to the result is in |*out|. Note that, even if |*out| is already non-
+// NULL on entry, it will not be written to. Rather, a fresh |EVP_PKEY| is
+// allocated and the previous one is freed. On successful exit, |*inp| is
+// advanced past the decoded key. It returns the result or NULL on error.
+//
+// RSA keys are parsed as a DER-encoded RSAPublicKey (RFC 3447) structure.
+// Parsing EC keys is not supported by this function.
+//
+// Use |RSA_parse_public_key| instead.
+OPENSSL_EXPORT EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **out,
+ const uint8_t **inp, long len);
+
// EVP_PKEY_get0_DH returns NULL.
OPENSSL_EXPORT DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey);
diff --git a/include/openssl/mem.h b/include/openssl/mem.h
index 9f9c00d..4e1c2ca 100644
--- a/include/openssl/mem.h
+++ b/include/openssl/mem.h
@@ -136,6 +136,10 @@
#define CRYPTO_realloc OPENSSL_realloc
#define CRYPTO_free OPENSSL_free
+// OPENSSL_clear_free calls |OPENSSL_free|. BoringSSL automatically clears all
+// allocations on free, but we define |OPENSSL_clear_free| for compatibility.
+#define OPENSSL_clear_free(ptr, len) OPENSSL_free(ptr)
+
#if defined(__cplusplus)
} // extern C