tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

crypto_rsa_nss.c (21054B)


      1 /* Copyright (c) 2001, Matej Pfajfar.
      2 * Copyright (c) 2001-2004, Roger Dingledine.
      3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      5 /* See LICENSE for licensing information */
      6 
      7 /**
      8 * \file crypto_rsa.c
      9 * \brief NSS implementations of our RSA code.
     10 **/
     11 
     12 #include "lib/crypt_ops/crypto_rsa.h"
     13 
     14 #include "lib/crypt_ops/crypto_nss_mgt.h"
     15 #include "lib/crypt_ops/crypto_util.h"
     16 #include "lib/ctime/di_ops.h"
     17 #include "lib/encoding/binascii.h"
     18 #include "lib/fs/files.h"
     19 #include "lib/intmath/cmp.h"
     20 #include "lib/intmath/muldiv.h"
     21 #include "lib/log/log.h"
     22 #include "lib/log/util_bug.h"
     23 
     24 #include <string.h>
     25 
     26 DISABLE_GCC_WARNING("-Wstrict-prototypes")
     27 #include <keyhi.h>
     28 #include <pk11pub.h>
     29 #include <secder.h>
     30 ENABLE_GCC_WARNING("-Wstrict-prototypes")
     31 
     32 #ifdef ENABLE_OPENSSL
     33 #include <openssl/rsa.h>
     34 #include <openssl/evp.h>
     35 #endif
     36 
     37 /** Declaration for crypto_pk_t structure. */
     38 struct crypto_pk_t
     39 {
     40  SECKEYPrivateKey *seckey;
     41  SECKEYPublicKey *pubkey;
     42 };
     43 
     44 /** Return true iff <b>key</b> contains the private-key portion of the RSA
     45 * key. */
     46 int
     47 crypto_pk_key_is_private(const crypto_pk_t *key)
     48 {
     49  return key && key->seckey;
     50 }
     51 
     52 /** used by tortls.c: wrap a SecKEYPublicKey in a crypto_pk_t. Take ownership
     53 * of the RSA object. */
     54 crypto_pk_t *
     55 crypto_pk_new_from_nss_pubkey(struct SECKEYPublicKeyStr *pub)
     56 {
     57  crypto_pk_t *result = tor_malloc_zero(sizeof(crypto_pk_t));
     58  result->pubkey = pub;
     59  return result;
     60 }
     61 
     62 /** Return the SECKEYPublicKey for the provided crypto_pk_t. */
     63 const SECKEYPublicKey *
     64 crypto_pk_get_nss_pubkey(const crypto_pk_t *key)
     65 {
     66  tor_assert(key);
     67  return key->pubkey;
     68 }
     69 
     70 /** Return the SECKEYPrivateKey for the provided crypto_pk_t, or NULL if it
     71 * does not exist. */
     72 const SECKEYPrivateKey *
     73 crypto_pk_get_nss_privkey(const crypto_pk_t *key)
     74 {
     75  tor_assert(key);
     76  return key->seckey;
     77 }
     78 
     79 #ifdef ENABLE_OPENSSL
     80 /** used by tortls.c: wrap an RSA* in a crypto_pk_t. Take ownership of the
     81 * RSA object. */
     82 crypto_pk_t *
     83 crypto_new_pk_from_openssl_rsa_(RSA *rsa)
     84 {
     85  crypto_pk_t *pk = NULL;
     86  unsigned char *buf = NULL;
     87  int len = i2d_RSAPublicKey(rsa, &buf);
     88  RSA_free(rsa);
     89 
     90  if (len < 0 || buf == NULL)
     91    goto end;
     92 
     93  pk = crypto_pk_asn1_decode((const char *)buf, len);
     94 
     95 end:
     96  if (buf)
     97    OPENSSL_free(buf);
     98  return pk;
     99 }
    100 
    101 /** Helper, used by tor-gencert.c.  Return the RSA from a
    102 * crypto_pk_t. */
    103 struct rsa_st *
    104 crypto_pk_get_openssl_rsa_(crypto_pk_t *pk)
    105 {
    106  size_t buflen = crypto_pk_keysize(pk)*16;
    107  unsigned char *buf = tor_malloc_zero(buflen);
    108  const unsigned char *cp = buf;
    109  RSA *rsa = NULL;
    110 
    111  int used = crypto_pk_asn1_encode_private(pk, (char*)buf, buflen);
    112  if (used < 0)
    113    goto end;
    114  rsa = d2i_RSAPrivateKey(NULL, &cp, used);
    115 
    116 end:
    117  memwipe(buf, 0, buflen);
    118  tor_free(buf);
    119  return rsa;
    120 }
    121 
    122 /** used by tortls.c: get an equivalent EVP_PKEY* for a crypto_pk_t.  Iff
    123 * private is set, include the private-key portion of the key. Return a valid
    124 * pointer on success, and NULL on failure. */
    125 MOCK_IMPL(struct evp_pkey_st *,
    126 crypto_pk_get_openssl_evp_pkey_,(crypto_pk_t *pk, int private))
    127 {
    128  size_t buflen = crypto_pk_keysize(pk)*16;
    129  unsigned char *buf = tor_malloc_zero(buflen);
    130  const unsigned char *cp = buf;
    131  RSA *rsa = NULL;
    132  EVP_PKEY *result = NULL;
    133 
    134  if (private) {
    135    int len = crypto_pk_asn1_encode_private(pk, (char*)buf, buflen);
    136    if (len < 0)
    137      goto end;
    138    rsa = d2i_RSAPrivateKey(NULL, &cp, len);
    139  } else {
    140    int len = crypto_pk_asn1_encode(pk, (char*)buf, buflen);
    141    if (len < 0)
    142      goto end;
    143    rsa = d2i_RSAPublicKey(NULL, &cp, len);
    144  }
    145  if (!rsa)
    146    goto end;
    147 
    148  if (!(result = EVP_PKEY_new()))
    149    goto end;
    150  if (!(EVP_PKEY_assign_RSA(result, rsa))) {
    151    EVP_PKEY_free(result);
    152    RSA_free(rsa);
    153    result = NULL;
    154  }
    155 
    156 end:
    157  memwipe(buf, 0, buflen);
    158  tor_free(buf);
    159  return result;
    160 }
    161 #endif /* defined(ENABLE_OPENSSL) */
    162 
    163 /** Allocate and return storage for a public key.  The key itself will not yet
    164 * be set.
    165 */
    166 MOCK_IMPL(crypto_pk_t *,
    167 crypto_pk_new,(void))
    168 {
    169  crypto_pk_t *result = tor_malloc_zero(sizeof(crypto_pk_t));
    170  return result;
    171 }
    172 
    173 /** Release the NSS objects held in <b>key</b> */
    174 static void
    175 crypto_pk_clear(crypto_pk_t *key)
    176 {
    177  if (key->pubkey)
    178    SECKEY_DestroyPublicKey(key->pubkey);
    179  if (key->seckey)
    180    SECKEY_DestroyPrivateKey(key->seckey);
    181  memset(key, 0, sizeof(crypto_pk_t));
    182 }
    183 
    184 /** Release a reference to an asymmetric key; when all the references
    185 * are released, free the key.
    186 */
    187 void
    188 crypto_pk_free_(crypto_pk_t *key)
    189 {
    190  if (!key)
    191    return;
    192 
    193  crypto_pk_clear(key);
    194 
    195  tor_free(key);
    196 }
    197 
    198 /** Generate a <b>bits</b>-bit new public/private keypair in <b>env</b>.
    199 * Return 0 on success, -1 on failure.
    200 */
    201 MOCK_IMPL(int,
    202 crypto_pk_generate_key_with_bits,(crypto_pk_t *key, int bits))
    203 {
    204  tor_assert(key);
    205 
    206  PK11RSAGenParams params = {
    207    .keySizeInBits = bits,
    208    .pe = TOR_RSA_EXPONENT
    209  };
    210 
    211  int result = -1;
    212  PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN, NULL);
    213  SECKEYPrivateKey *seckey = NULL;
    214  SECKEYPublicKey *pubkey = NULL;
    215 
    216  if (!slot) {
    217    crypto_nss_log_errors(LOG_WARN, "getting slot for RSA keygen");
    218    goto done;
    219  }
    220 
    221  seckey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &params,
    222                                &pubkey,
    223                                PR_FALSE /*isPerm */,
    224                                PR_FALSE /*isSensitive*/,
    225                                NULL);
    226  if (seckey == NULL || pubkey == NULL) {
    227    crypto_nss_log_errors(LOG_WARN, "generating an RSA key");
    228    goto done;
    229  }
    230 
    231  crypto_pk_clear(key);
    232  key->seckey = seckey;
    233  key->pubkey = pubkey;
    234  seckey = NULL;
    235  pubkey = NULL;
    236 
    237  result = 0;
    238 done:
    239  if (slot)
    240    PK11_FreeSlot(slot);
    241  if (pubkey)
    242    SECKEY_DestroyPublicKey(pubkey);
    243  if (seckey)
    244    SECKEY_DestroyPrivateKey(seckey);
    245 
    246  return result;
    247 }
    248 
    249 /** Return true iff <b>env</b> is a valid private key.
    250 */
    251 int
    252 crypto_pk_is_valid_private_key(const crypto_pk_t *key)
    253 {
    254  /* We don't need to do validation here, since unlike OpenSSL, NSS won't let
    255   * us load private keys without validating them. */
    256  return key && key->seckey;
    257 }
    258 
    259 /** Return true iff <b>env</b> contains a public key whose public exponent
    260 * equals 65537.
    261 */
    262 int
    263 crypto_pk_public_exponent_ok(const crypto_pk_t *key)
    264 {
    265  return key &&
    266    key->pubkey &&
    267    key->pubkey->keyType == rsaKey &&
    268    DER_GetUInteger(&key->pubkey->u.rsa.publicExponent) == TOR_RSA_EXPONENT;
    269 }
    270 
    271 /** Compare two big-endian integers stored in a and b; return a tristate.
    272 */
    273 STATIC int
    274 secitem_uint_cmp(const SECItem *a, const SECItem *b)
    275 {
    276  const unsigned abits = SECKEY_BigIntegerBitLength(a);
    277  const unsigned bbits = SECKEY_BigIntegerBitLength(b);
    278 
    279  if (abits < bbits)
    280    return -1;
    281  else if (abits > bbits)
    282    return 1;
    283 
    284  /* okay, they have the same number of bits set. Get a pair of aligned
    285   * pointers to their bytes that are set... */
    286  const unsigned nbytes = CEIL_DIV(abits, 8);
    287  tor_assert(nbytes <= a->len);
    288  tor_assert(nbytes <= b->len);
    289 
    290  const unsigned char *aptr = a->data + (a->len - nbytes);
    291  const unsigned char *bptr = b->data + (b->len - nbytes);
    292 
    293  /* And compare them. */
    294  return fast_memcmp(aptr, bptr, nbytes);
    295 }
    296 
    297 /** Compare the public-key components of a and b.  Return less than 0
    298 * if a\<b, 0 if a==b, and greater than 0 if a\>b.  A NULL key is
    299 * considered to be less than all non-NULL keys, and equal to itself.
    300 *
    301 * Note that this may leak information about the keys through timing.
    302 */
    303 int
    304 crypto_pk_cmp_keys(const crypto_pk_t *a, const crypto_pk_t *b)
    305 {
    306  int result;
    307  char a_is_non_null = (a != NULL) && (a->pubkey != NULL);
    308  char b_is_non_null = (b != NULL) && (b->pubkey != NULL);
    309  char an_argument_is_null = !a_is_non_null | !b_is_non_null;
    310 
    311  result = tor_memcmp(&a_is_non_null, &b_is_non_null, sizeof(a_is_non_null));
    312  if (an_argument_is_null)
    313    return result;
    314 
    315  // This is all Tor uses with this structure.
    316  tor_assert(a->pubkey->keyType == rsaKey);
    317  tor_assert(b->pubkey->keyType == rsaKey);
    318 
    319  const SECItem *a_n, *a_e, *b_n, *b_e;
    320  a_n = &a->pubkey->u.rsa.modulus;
    321  b_n = &b->pubkey->u.rsa.modulus;
    322  a_e = &a->pubkey->u.rsa.publicExponent;
    323  b_e = &b->pubkey->u.rsa.publicExponent;
    324 
    325  result = secitem_uint_cmp(a_n, b_n);
    326  if (result)
    327    return result;
    328  return secitem_uint_cmp(a_e, b_e);
    329 }
    330 
    331 /** Return the size of the public key modulus in <b>env</b>, in bytes. */
    332 size_t
    333 crypto_pk_keysize(const crypto_pk_t *key)
    334 {
    335  tor_assert(key);
    336  tor_assert(key->pubkey);
    337  return SECKEY_PublicKeyStrength(key->pubkey);
    338 }
    339 
    340 /** Return the size of the public key modulus of <b>env</b>, in bits. */
    341 int
    342 crypto_pk_num_bits(crypto_pk_t *key)
    343 {
    344  tor_assert(key);
    345  tor_assert(key->pubkey);
    346  return SECKEY_PublicKeyStrengthInBits(key->pubkey);
    347 }
    348 
    349 /**
    350 * Make a copy of <b>key</b> and return it.
    351 */
    352 crypto_pk_t *
    353 crypto_pk_dup_key(crypto_pk_t *key)
    354 {
    355  crypto_pk_t *result = crypto_pk_new();
    356  if (key->pubkey)
    357    result->pubkey = SECKEY_CopyPublicKey(key->pubkey);
    358  if (key->seckey)
    359    result->seckey = SECKEY_CopyPrivateKey(key->seckey);
    360  return result;
    361 }
    362 
    363 /** For testing: replace dest with src.  (Dest must have a refcount
    364 * of 1) */
    365 void
    366 crypto_pk_assign_public(crypto_pk_t *dest, const crypto_pk_t *src)
    367 {
    368  crypto_pk_clear(dest);
    369  if (src->pubkey)
    370    dest->pubkey = SECKEY_CopyPublicKey(src->pubkey);
    371 }
    372 
    373 /** For testing: replace dest with src.  (Dest must have a refcount
    374 * of 1) */
    375 void
    376 crypto_pk_assign_private(crypto_pk_t *dest, const crypto_pk_t *src)
    377 {
    378  crypto_pk_clear(dest);
    379  if (src->pubkey)
    380    dest->pubkey = SECKEY_CopyPublicKey(src->pubkey);
    381  if (src->seckey)
    382    dest->seckey = SECKEY_CopyPrivateKey(src->seckey);
    383 }
    384 
    385 /** Make a real honest-to-goodness copy of <b>env</b>, and return it.
    386 * Returns NULL on failure. */
    387 crypto_pk_t *
    388 crypto_pk_copy_full(crypto_pk_t *key)
    389 {
    390  // These aren't reference-counted is nss, so it's fine to just
    391  // use the same function.
    392  return crypto_pk_dup_key(key);
    393 }
    394 
    395 static const CK_RSA_PKCS_OAEP_PARAMS oaep_params = {
    396            .hashAlg = CKM_SHA_1,
    397            .mgf = CKG_MGF1_SHA1,
    398            .source = CKZ_DATA_SPECIFIED,
    399            .pSourceData = NULL,
    400            .ulSourceDataLen = 0
    401 };
    402 static const SECItem oaep_item = {
    403            .type = siBuffer,
    404            .data = (unsigned char *) &oaep_params,
    405            .len = sizeof(oaep_params)
    406 };
    407 
    408 /** Return the mechanism code and parameters for a given padding method when
    409 * used with RSA */
    410 static CK_MECHANISM_TYPE
    411 padding_to_mechanism(int padding, SECItem **item_out)
    412 {
    413  switch (padding) {
    414    case PK_PKCS1_OAEP_PADDING:
    415      *item_out = (SECItem *)&oaep_item;
    416      return CKM_RSA_PKCS_OAEP;
    417    default:
    418      tor_assert_unreached();
    419      *item_out = NULL;
    420      return CKM_INVALID_MECHANISM;
    421  }
    422 }
    423 
    424 /** Encrypt <b>fromlen</b> bytes from <b>from</b> with the public key
    425 * in <b>env</b>, using the padding method <b>padding</b>.  On success,
    426 * write the result to <b>to</b>, and return the number of bytes
    427 * written.  On failure, return -1.
    428 *
    429 * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
    430 * at least the length of the modulus of <b>env</b>.
    431 */
    432 int
    433 crypto_pk_public_encrypt(crypto_pk_t *env, char *to, size_t tolen,
    434                         const char *from, size_t fromlen, int padding)
    435 {
    436  tor_assert(env);
    437  tor_assert(to);
    438  tor_assert(from);
    439  tor_assert(tolen < INT_MAX);
    440  tor_assert(fromlen < INT_MAX);
    441 
    442  if (BUG(! env->pubkey))
    443    return -1;
    444 
    445  unsigned int result_len = 0;
    446  SECItem *item = NULL;
    447  CK_MECHANISM_TYPE m = padding_to_mechanism(padding, &item);
    448 
    449  SECStatus s = PK11_PubEncrypt(env->pubkey, m, item,
    450                                (unsigned char *)to, &result_len,
    451                                (unsigned int)tolen,
    452                                (const unsigned char *)from,
    453                                (unsigned int)fromlen,
    454                                NULL);
    455  if (s != SECSuccess) {
    456    crypto_nss_log_errors(LOG_WARN, "encrypting to an RSA key");
    457    return -1;
    458  }
    459 
    460  return (int)result_len;
    461 }
    462 
    463 /** Decrypt <b>fromlen</b> bytes from <b>from</b> with the private key
    464 * in <b>env</b>, using the padding method <b>padding</b>.  On success,
    465 * write the result to <b>to</b>, and return the number of bytes
    466 * written.  On failure, return -1.
    467 *
    468 * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
    469 * at least the length of the modulus of <b>key</b>.
    470 */
    471 int
    472 crypto_pk_private_decrypt(crypto_pk_t *key, char *to,
    473                          size_t tolen,
    474                          const char *from, size_t fromlen,
    475                          int padding, int warnOnFailure)
    476 {
    477  tor_assert(key);
    478  tor_assert(to);
    479  tor_assert(from);
    480  tor_assert(tolen < INT_MAX);
    481  tor_assert(fromlen < INT_MAX);
    482 
    483  if (!crypto_pk_key_is_private(key))
    484    return -1; /* Not a private key. */
    485 
    486  unsigned int result_len = 0;
    487  SECItem *item = NULL;
    488  CK_MECHANISM_TYPE m = padding_to_mechanism(padding, &item);
    489  SECStatus s = PK11_PrivDecrypt(key->seckey, m, item,
    490                                 (unsigned char *)to, &result_len,
    491                                 (unsigned int)tolen,
    492                                 (const unsigned char *)from,
    493                                 (unsigned int)fromlen);
    494 
    495  if (s != SECSuccess) {
    496    const int severity = warnOnFailure ? LOG_WARN : LOG_INFO;
    497    crypto_nss_log_errors(severity, "decrypting with an RSA key");
    498    return -1;
    499  }
    500 
    501  return (int)result_len;
    502 }
    503 
    504 /** Check the signature in <b>from</b> (<b>fromlen</b> bytes long) with the
    505 * public key in <b>key</b>, using PKCS1 padding.  On success, write the
    506 * signed data to <b>to</b>, and return the number of bytes written.
    507 * On failure, return -1.
    508 *
    509 * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
    510 * at least the length of the modulus of <b>key</b>.
    511 */
    512 MOCK_IMPL(int,
    513 crypto_pk_public_checksig,(const crypto_pk_t *key, char *to,
    514                           size_t tolen,
    515                           const char *from, size_t fromlen))
    516 {
    517  tor_assert(key);
    518  tor_assert(to);
    519  tor_assert(from);
    520  tor_assert(tolen < INT_MAX);
    521  tor_assert(fromlen < INT_MAX);
    522  tor_assert(key->pubkey);
    523 
    524  SECItem sig = {
    525                 .type = siBuffer,
    526                 .data = (unsigned char *) from,
    527                 .len = (unsigned int) fromlen,
    528  };
    529  SECItem dsig = {
    530                  .type = siBuffer,
    531                  .data = (unsigned char *) to,
    532                  .len = (unsigned int) tolen
    533  };
    534  SECStatus s;
    535  s = PK11_VerifyRecover(key->pubkey, &sig, &dsig, NULL);
    536  if (s != SECSuccess)
    537    return -1;
    538 
    539  return (int)dsig.len;
    540 }
    541 
    542 /** Sign <b>fromlen</b> bytes of data from <b>from</b> with the private key in
    543 * <b>env</b>, using PKCS1 padding.  On success, write the signature to
    544 * <b>to</b>, and return the number of bytes written.  On failure, return
    545 * -1.
    546 *
    547 * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
    548 * at least the length of the modulus of <b>env</b>.
    549 */
    550 int
    551 crypto_pk_private_sign(const crypto_pk_t *key, char *to, size_t tolen,
    552                       const char *from, size_t fromlen)
    553 {
    554  tor_assert(key);
    555  tor_assert(to);
    556  tor_assert(from);
    557  tor_assert(tolen < INT_MAX);
    558  tor_assert(fromlen < INT_MAX);
    559 
    560  if (BUG(!crypto_pk_key_is_private(key)))
    561    return -1;
    562 
    563  SECItem sig = {
    564                 .type = siBuffer,
    565                 .data = (unsigned char *)to,
    566                 .len = (unsigned int) tolen
    567  };
    568  SECItem hash = {
    569                 .type = siBuffer,
    570                 .data = (unsigned char *)from,
    571                 .len = (unsigned int) fromlen
    572  };
    573  CK_MECHANISM_TYPE m = CKM_RSA_PKCS;
    574  SECStatus s = PK11_SignWithMechanism(key->seckey, m, NULL,
    575                                       &sig, &hash);
    576 
    577  if (s != SECSuccess) {
    578    crypto_nss_log_errors(LOG_WARN, "signing with an RSA key");
    579    return -1;
    580  }
    581 
    582  return (int)sig.len;
    583 }
    584 
    585 /* "This has lead to people trading hard-to-find object identifiers and ASN.1
    586 * definitions like baseball cards" - Peter Gutmann, "X.509 Style Guide". */
    587 static const unsigned char RSA_OID[] = {
    588  /* RSADSI */ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
    589  /* PKCS1 */ 0x01, 0x01,
    590  /* RSA */ 0x01
    591 };
    592 
    593 /** ASN.1-encode the public portion of <b>pk</b> into <b>dest</b>.
    594 * Return -1 on error, or the number of characters used on success.
    595 */
    596 int
    597 crypto_pk_asn1_encode(const crypto_pk_t *pk, char *dest, size_t dest_len)
    598 {
    599  tor_assert(pk);
    600  if (pk->pubkey == NULL)
    601    return -1;
    602 
    603  CERTSubjectPublicKeyInfo *info;
    604  info = SECKEY_CreateSubjectPublicKeyInfo(pk->pubkey);
    605  if (! info)
    606    return -1;
    607 
    608  const SECItem *item = &info->subjectPublicKey;
    609  size_t actual_len = (item->len) >> 3; /* bits to bytes */
    610  size_t n_used = MIN(actual_len, dest_len);
    611  memcpy(dest, item->data, n_used);
    612 
    613  SECKEY_DestroySubjectPublicKeyInfo(info);
    614  return (int) n_used;
    615 }
    616 
    617 /** Decode an ASN.1-encoded public key from <b>str</b>; return the result on
    618 * success and NULL on failure.
    619 */
    620 crypto_pk_t *
    621 crypto_pk_asn1_decode(const char *str, size_t len)
    622 {
    623  tor_assert(str);
    624  if (len >= INT_MAX)
    625    return NULL;
    626  CERTSubjectPublicKeyInfo info = {
    627             .algorithm = {
    628                           .algorithm = {
    629                                         .type = siDEROID,
    630                                         .data = (unsigned char *)RSA_OID,
    631                                         .len = sizeof(RSA_OID)
    632                                           }
    633                           },
    634             .subjectPublicKey = {
    635                   .type = siBuffer,
    636                   .data = (unsigned char *)str,
    637                   .len = (unsigned int)(len << 3) /* bytes to bits */
    638                                  }
    639  };
    640 
    641  SECKEYPublicKey *pub = SECKEY_ExtractPublicKey(&info);
    642  if (pub == NULL)
    643    return NULL;
    644 
    645  crypto_pk_t *result = crypto_pk_new();
    646  result->pubkey = pub;
    647  return result;
    648 }
    649 
    650 DISABLE_GCC_WARNING("-Wunused-parameter")
    651 
    652 /** Given a crypto_pk_t <b>pk</b>, allocate a new buffer containing the Base64
    653 * encoding of the DER representation of the private key into the
    654 * <b>dest_len</b>-byte buffer in <b>dest</b>.
    655 * Return the number of bytes written on success, -1 on failure.
    656 */
    657 int
    658 crypto_pk_asn1_encode_private(const crypto_pk_t *pk,
    659                              char *dest, size_t destlen)
    660 {
    661  tor_assert(destlen <= INT_MAX);
    662  if (!crypto_pk_key_is_private(pk))
    663    return -1;
    664 
    665  SECKEYPrivateKeyInfo *info = PK11_ExportPrivKeyInfo(pk->seckey, NULL);
    666  if (!info)
    667    return -1;
    668  SECItem *item = &info->privateKey;
    669 
    670  if (destlen < item->len) {
    671    SECKEY_DestroyPrivateKeyInfo(info, PR_TRUE);
    672    return -1;
    673  }
    674  int result = (int)item->len;
    675  memcpy(dest, item->data, item->len);
    676  SECKEY_DestroyPrivateKeyInfo(info, PR_TRUE);
    677 
    678  return result;
    679 }
    680 
    681 /** Given a buffer containing the DER representation of the
    682 * private key <b>str</b>, decode and return the result on success, or NULL
    683 * on failure.
    684 *
    685 * If <b>max_bits</b> is nonnegative, reject any key longer than max_bits
    686 * without performing any expensive validation on it.
    687 */
    688 crypto_pk_t *
    689 crypto_pk_asn1_decode_private(const char *str, size_t len, int max_bits)
    690 {
    691  tor_assert(str);
    692  tor_assert(len < INT_MAX);
    693  PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS, NULL);
    694  if (!slot)
    695    return NULL;
    696 
    697  SECKEYPrivateKeyInfo info = {
    698             .algorithm = {
    699                           .algorithm = {
    700                                         .type = siBuffer,
    701                                         .data = (unsigned char *)RSA_OID,
    702                                         .len = sizeof(RSA_OID)
    703                                           }
    704                           },
    705             .privateKey = {
    706                            .type = siBuffer,
    707                            .data = (unsigned char *)str,
    708                            .len = (int)len,
    709                            }
    710  };
    711 
    712  SECStatus s;
    713  SECKEYPrivateKey *seckey = NULL;
    714 
    715  s = PK11_ImportPrivateKeyInfoAndReturnKey(slot, &info,
    716                                            NULL /* nickname */,
    717                                            NULL /* publicValue */,
    718                                            PR_FALSE /* isPerm */,
    719                                            PR_FALSE /* isPrivate */,
    720                                            KU_ALL /* keyUsage */,
    721                                            &seckey, NULL);
    722 
    723  crypto_pk_t *output = NULL;
    724 
    725  if (s == SECSuccess && seckey) {
    726    output = crypto_pk_new();
    727    output->seckey = seckey;
    728    output->pubkey = SECKEY_ConvertToPublicKey(seckey);
    729    tor_assert(output->pubkey);
    730  } else {
    731    crypto_nss_log_errors(LOG_WARN, "decoding an RSA private key");
    732  }
    733 
    734  if (! crypto_pk_is_valid_private_key(output)) {
    735    crypto_pk_free(output);
    736    output = NULL;
    737  }
    738 
    739  if (output) {
    740    const int bits = SECKEY_PublicKeyStrengthInBits(output->pubkey);
    741    if (max_bits >= 0 && bits > max_bits) {
    742      log_info(LD_CRYPTO, "Private key longer than expected.");
    743      crypto_pk_free(output);
    744      output = NULL;
    745    }
    746  }
    747 
    748  if (slot)
    749    PK11_FreeSlot(slot);
    750 
    751  return output;
    752 }