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