LCOV - code coverage report
Current view: top level - lib/crypt_ops - crypto_rsa.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 265 296 89.5 %
Date: 2021-11-24 03:28:48 Functions: 22 23 95.7 %

          Line data    Source code
       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 Block of functions related with RSA utilities and operations.
      10             :  **/
      11             : 
      12             : #include "lib/crypt_ops/crypto_cipher.h"
      13             : #include "lib/crypt_ops/crypto_curve25519.h"
      14             : #include "lib/crypt_ops/crypto_digest.h"
      15             : #include "lib/crypt_ops/crypto_format.h"
      16             : #include "lib/crypt_ops/compat_openssl.h"
      17             : #include "lib/crypt_ops/crypto_rand.h"
      18             : #include "lib/crypt_ops/crypto_rsa.h"
      19             : #include "lib/crypt_ops/crypto_util.h"
      20             : #include "lib/ctime/di_ops.h"
      21             : #include "lib/log/util_bug.h"
      22             : #include "lib/fs/files.h"
      23             : 
      24             : #include "lib/log/escape.h"
      25             : #include "lib/log/log.h"
      26             : #include "lib/encoding/binascii.h"
      27             : #include "lib/encoding/pem.h"
      28             : 
      29             : #include <string.h>
      30             : #ifdef HAVE_SYS_STAT_H
      31             : #include <sys/stat.h>
      32             : #endif
      33             : 
      34             : #ifdef ENABLE_OPENSSL
      35             : #include <openssl/rsa.h>
      36             : #endif
      37             : 
      38             : /** Return the number of bytes added by padding method <b>padding</b>.
      39             :  */
      40             : int
      41          58 : crypto_get_rsa_padding_overhead(int padding)
      42             : {
      43          58 :   switch (padding)
      44             :     {
      45          58 :     case PK_PKCS1_OAEP_PADDING: return PKCS1_OAEP_PADDING_OVERHEAD;
      46             :     default: tor_assert(0); return -1; // LCOV_EXCL_LINE
      47             :     }
      48             : }
      49             : 
      50             : #ifdef ENABLE_OPENSSL
      51             : /** Given a padding method <b>padding</b>, return the correct OpenSSL constant.
      52             :  */
      53             : int
      54         129 : crypto_get_rsa_padding(int padding)
      55             : {
      56         129 :   switch (padding)
      57             :     {
      58         129 :     case PK_PKCS1_OAEP_PADDING: return RSA_PKCS1_OAEP_PADDING;
      59             :     default: tor_assert(0); return -1; // LCOV_EXCL_LINE
      60             :     }
      61             : }
      62             : #endif /* defined(ENABLE_OPENSSL) */
      63             : 
      64             : /** Compare the public-key components of a and b.  Return non-zero iff
      65             :  * a==b.  A NULL key is considered to be distinct from all non-NULL
      66             :  * keys, and equal to itself.
      67             :  *
      68             :  *  Note that this may leak information about the keys through timing.
      69             :  */
      70             : int
      71          19 : crypto_pk_eq_keys(const crypto_pk_t *a, const crypto_pk_t *b)
      72             : {
      73          19 :   return (crypto_pk_cmp_keys(a, b) == 0);
      74             : }
      75             : 
      76             : /** Perform a hybrid (public/secret) encryption on <b>fromlen</b>
      77             :  * bytes of data from <b>from</b>, with padding type 'padding',
      78             :  * storing the results on <b>to</b>.
      79             :  *
      80             :  * Returns the number of bytes written on success, -1 on failure.
      81             :  *
      82             :  * The encrypted data consists of:
      83             :  *   - The source data, padded and encrypted with the public key, if the
      84             :  *     padded source data is no longer than the public key, and <b>force</b>
      85             :  *     is false, OR
      86             :  *   - The beginning of the source data prefixed with a 16-byte symmetric key,
      87             :  *     padded and encrypted with the public key; followed by the rest of
      88             :  *     the source data encrypted in AES-CTR mode with the symmetric key.
      89             :  *
      90             :  * NOTE that this format does not authenticate the symmetrically encrypted
      91             :  * part of the data, and SHOULD NOT BE USED for new protocols.
      92             :  */
      93             : int
      94          58 : crypto_pk_obsolete_public_hybrid_encrypt(crypto_pk_t *env,
      95             :                                 char *to, size_t tolen,
      96             :                                 const char *from,
      97             :                                 size_t fromlen,
      98             :                                 int padding, int force)
      99             : {
     100          58 :   int overhead, outlen, r;
     101          58 :   size_t pkeylen, symlen;
     102          58 :   crypto_cipher_t *cipher = NULL;
     103          58 :   char *buf = NULL;
     104             : 
     105          58 :   tor_assert(env);
     106          58 :   tor_assert(from);
     107          58 :   tor_assert(to);
     108          58 :   tor_assert(fromlen < SIZE_T_CEILING);
     109             : 
     110          58 :   overhead = crypto_get_rsa_padding_overhead(padding);
     111          58 :   pkeylen = crypto_pk_keysize(env);
     112             : 
     113          58 :   if (!force && fromlen+overhead <= pkeylen) {
     114             :     /* It all fits in a single encrypt. */
     115           2 :     return crypto_pk_public_encrypt(env,to,
     116             :                                     tolen,
     117             :                                     from,fromlen,padding);
     118             :   }
     119          56 :   tor_assert(tolen >= fromlen + overhead + CIPHER_KEY_LEN);
     120          56 :   tor_assert(tolen >= pkeylen);
     121             : 
     122          56 :   char key[CIPHER_KEY_LEN];
     123          56 :   crypto_rand(key, sizeof(key)); /* generate a new key. */
     124          56 :   cipher = crypto_cipher_new(key);
     125             : 
     126          56 :   buf = tor_malloc(pkeylen+1);
     127          56 :   memcpy(buf, key, CIPHER_KEY_LEN);
     128          56 :   memcpy(buf+CIPHER_KEY_LEN, from, pkeylen-overhead-CIPHER_KEY_LEN);
     129             : 
     130             :   /* Length of symmetrically encrypted data. */
     131          56 :   symlen = fromlen-(pkeylen-overhead-CIPHER_KEY_LEN);
     132             : 
     133          56 :   outlen = crypto_pk_public_encrypt(env,to,tolen,buf,pkeylen-overhead,padding);
     134          56 :   if (outlen!=(int)pkeylen) {
     135           0 :     goto err;
     136             :   }
     137          56 :   r = crypto_cipher_encrypt(cipher, to+outlen,
     138             :                             from+pkeylen-overhead-CIPHER_KEY_LEN, symlen);
     139             : 
     140          56 :   if (r<0) goto err;
     141          56 :   memwipe(buf, 0, pkeylen);
     142          56 :   memwipe(key, 0, sizeof(key));
     143          56 :   tor_free(buf);
     144          56 :   crypto_cipher_free(cipher);
     145          56 :   tor_assert(outlen+symlen < INT_MAX);
     146          56 :   return (int)(outlen + symlen);
     147           0 :  err:
     148             : 
     149           0 :   memwipe(buf, 0, pkeylen);
     150           0 :   memwipe(key, 0, sizeof(key));
     151           0 :   tor_free(buf);
     152           0 :   crypto_cipher_free(cipher);
     153           0 :   return -1;
     154             : }
     155             : 
     156             : /** Invert crypto_pk_obsolete_public_hybrid_encrypt. Returns the number of
     157             :  * bytes written on success, -1 on failure.
     158             :  *
     159             :  * NOTE that this format does not authenticate the symmetrically encrypted
     160             :  * part of the data, and SHOULD NOT BE USED for new protocols.
     161             :  */
     162             : int
     163          64 : crypto_pk_obsolete_private_hybrid_decrypt(crypto_pk_t *env,
     164             :                                  char *to,
     165             :                                  size_t tolen,
     166             :                                  const char *from,
     167             :                                  size_t fromlen,
     168             :                                  int padding, int warnOnFailure)
     169             : {
     170          64 :   int outlen, r;
     171          64 :   size_t pkeylen;
     172          64 :   crypto_cipher_t *cipher = NULL;
     173          64 :   char *buf = NULL;
     174             : 
     175          64 :   tor_assert(fromlen < SIZE_T_CEILING);
     176          64 :   pkeylen = crypto_pk_keysize(env);
     177             : 
     178          64 :   if (fromlen <= pkeylen) {
     179           2 :     return crypto_pk_private_decrypt(env,to,tolen,from,fromlen,padding,
     180             :                                      warnOnFailure);
     181             :   }
     182             : 
     183          62 :   buf = tor_malloc(pkeylen);
     184          62 :   outlen = crypto_pk_private_decrypt(env,buf,pkeylen,from,pkeylen,padding,
     185             :                                      warnOnFailure);
     186          62 :   if (outlen<0) {
     187           6 :     log_fn(warnOnFailure?LOG_WARN:LOG_DEBUG, LD_CRYPTO,
     188             :            "Error decrypting public-key data");
     189           3 :     goto err;
     190             :   }
     191          59 :   if (outlen < CIPHER_KEY_LEN) {
     192           0 :     log_fn(warnOnFailure?LOG_WARN:LOG_INFO, LD_CRYPTO,
     193             :            "No room for a symmetric key");
     194           0 :     goto err;
     195             :   }
     196          59 :   cipher = crypto_cipher_new(buf);
     197          59 :   if (!cipher) {
     198           0 :     goto err;
     199             :   }
     200          59 :   memcpy(to,buf+CIPHER_KEY_LEN,outlen-CIPHER_KEY_LEN);
     201          59 :   outlen -= CIPHER_KEY_LEN;
     202          59 :   tor_assert(tolen - outlen >= fromlen - pkeylen);
     203          59 :   r = crypto_cipher_decrypt(cipher, to+outlen, from+pkeylen, fromlen-pkeylen);
     204          59 :   if (r<0)
     205           0 :     goto err;
     206          59 :   memwipe(buf,0,pkeylen);
     207          59 :   tor_free(buf);
     208          59 :   crypto_cipher_free(cipher);
     209          59 :   tor_assert(outlen + fromlen < INT_MAX);
     210          59 :   return (int)(outlen + (fromlen-pkeylen));
     211           3 :  err:
     212           3 :   memwipe(buf,0,pkeylen);
     213           3 :   tor_free(buf);
     214           3 :   crypto_cipher_free(cipher);
     215           3 :   return -1;
     216             : }
     217             : 
     218             : /** Given a private or public key <b>pk</b>, put a fingerprint of the
     219             :  * public key into <b>fp_out</b> (must have at least FINGERPRINT_LEN+1 bytes of
     220             :  * space).  Return 0 on success, -1 on failure.
     221             :  *
     222             :  * Fingerprints are computed as the SHA1 digest of the ASN.1 encoding
     223             :  * of the public key, converted to hexadecimal, in upper case, with a
     224             :  * space after every four digits.
     225             :  *
     226             :  * If <b>add_space</b> is false, omit the spaces.
     227             :  */
     228             : int
     229         150 : crypto_pk_get_fingerprint(crypto_pk_t *pk, char *fp_out, int add_space)
     230             : {
     231         150 :   char digest[DIGEST_LEN];
     232         150 :   char hexdigest[HEX_DIGEST_LEN+1];
     233         150 :   if (crypto_pk_get_digest(pk, digest)) {
     234             :     return -1;
     235             :   }
     236         150 :   base16_encode(hexdigest,sizeof(hexdigest),digest,DIGEST_LEN);
     237         150 :   if (add_space) {
     238          40 :     crypto_add_spaces_to_fp(fp_out, FINGERPRINT_LEN+1, hexdigest);
     239             :   } else {
     240         110 :     strncpy(fp_out, hexdigest, HEX_DIGEST_LEN+1);
     241             :   }
     242             :   return 0;
     243             : }
     244             : 
     245             : /** Given a private or public key <b>pk</b>, put a hashed fingerprint of
     246             :  * the public key into <b>fp_out</b> (must have at least FINGERPRINT_LEN+1
     247             :  * bytes of space).  Return 0 on success, -1 on failure.
     248             :  *
     249             :  * Hashed fingerprints are computed as the SHA1 digest of the SHA1 digest
     250             :  * of the ASN.1 encoding of the public key, converted to hexadecimal, in
     251             :  * upper case.
     252             :  */
     253             : int
     254           5 : crypto_pk_get_hashed_fingerprint(crypto_pk_t *pk, char *fp_out)
     255             : {
     256           5 :   char digest[DIGEST_LEN], hashed_digest[DIGEST_LEN];
     257           5 :   if (crypto_pk_get_digest(pk, digest)) {
     258             :     return -1;
     259             :   }
     260           5 :   if (crypto_digest(hashed_digest, digest, DIGEST_LEN) < 0) {
     261             :     return -1;
     262             :   }
     263           5 :   base16_encode(fp_out, FINGERPRINT_LEN + 1, hashed_digest, DIGEST_LEN);
     264           5 :   return 0;
     265             : }
     266             : 
     267             : /** Copy <b>in</b> to the <b>outlen</b>-byte buffer <b>out</b>, adding spaces
     268             :  * every four characters. */
     269             : void
     270          41 : crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in)
     271             : {
     272          41 :   int n = 0;
     273          41 :   char *end = out+outlen;
     274          41 :   tor_assert(outlen < SIZE_T_CEILING);
     275             : 
     276        1681 :   while (*in && out<end) {
     277        1640 :     *out++ = *in++;
     278        1640 :     if (++n == 4 && *in && out<end) {
     279         369 :       n = 0;
     280         369 :       *out++ = ' ';
     281             :     }
     282             :   }
     283          41 :   tor_assert(out<end);
     284          41 :   *out = '\0';
     285          41 : }
     286             : 
     287             : /** Check a siglen-byte long signature at <b>sig</b> against
     288             :  * <b>datalen</b> bytes of data at <b>data</b>, using the public key
     289             :  * in <b>env</b>. Return 0 if <b>sig</b> is a correct signature for
     290             :  * SHA1(data).  Else return -1.
     291             :  */
     292           2 : MOCK_IMPL(int,
     293             : crypto_pk_public_checksig_digest,(crypto_pk_t *env, const char *data,
     294             :                                   size_t datalen, const char *sig,
     295             :                                   size_t siglen))
     296             : {
     297           2 :   char digest[DIGEST_LEN];
     298           2 :   char *buf;
     299           2 :   size_t buflen;
     300           2 :   int r;
     301             : 
     302           2 :   tor_assert(env);
     303           2 :   tor_assert(data);
     304           2 :   tor_assert(sig);
     305           2 :   tor_assert(datalen < SIZE_T_CEILING);
     306           2 :   tor_assert(siglen < SIZE_T_CEILING);
     307             : 
     308           2 :   if (crypto_digest(digest,data,datalen)<0) {
     309           0 :     log_warn(LD_BUG, "couldn't compute digest");
     310           0 :     return -1;
     311             :   }
     312           2 :   buflen = crypto_pk_keysize(env);
     313           2 :   buf = tor_malloc(buflen);
     314           2 :   r = crypto_pk_public_checksig(env,buf,buflen,sig,siglen);
     315           2 :   if (r != DIGEST_LEN) {
     316           0 :     log_warn(LD_CRYPTO, "Invalid signature");
     317           0 :     tor_free(buf);
     318           0 :     return -1;
     319             :   }
     320           2 :   if (tor_memneq(buf, digest, DIGEST_LEN)) {
     321           1 :     log_warn(LD_CRYPTO, "Signature mismatched with digest.");
     322           1 :     tor_free(buf);
     323           1 :     return -1;
     324             :   }
     325           1 :   tor_free(buf);
     326             : 
     327           1 :   return 0;
     328             : }
     329             : 
     330             : /** Compute a SHA1 digest of <b>fromlen</b> bytes of data stored at
     331             :  * <b>from</b>; sign the data with the private key in <b>env</b>, and
     332             :  * store it in <b>to</b>.  Return the number of bytes written on
     333             :  * success, and -1 on failure.
     334             :  *
     335             :  * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
     336             :  * at least the length of the modulus of <b>env</b>.
     337             :  */
     338             : int
     339           1 : crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen,
     340             :                               const char *from, size_t fromlen)
     341             : {
     342           1 :   int r;
     343           1 :   char digest[DIGEST_LEN];
     344           1 :   if (crypto_digest(digest,from,fromlen)<0)
     345             :     return -1;
     346           1 :   r = crypto_pk_private_sign(env,to,tolen,digest,DIGEST_LEN);
     347           1 :   memwipe(digest, 0, sizeof(digest));
     348           1 :   return r;
     349             : }
     350             : 
     351             : /** Given a private or public key <b>pk</b>, put a SHA1 hash of the
     352             :  * public key into <b>digest_out</b> (must have DIGEST_LEN bytes of space).
     353             :  * Return 0 on success, -1 on failure.
     354             :  */
     355             : int
     356        1333 : crypto_pk_get_digest(const crypto_pk_t *pk, char *digest_out)
     357             : {
     358        1333 :   char *buf;
     359        1333 :   size_t buflen;
     360        1333 :   int len;
     361        1333 :   int rv = -1;
     362             : 
     363        1333 :   buflen = crypto_pk_keysize(pk)*2;
     364        1333 :   buf = tor_malloc(buflen);
     365        1333 :   len = crypto_pk_asn1_encode(pk, buf, buflen);
     366        1333 :   if (len < 0)
     367           2 :     goto done;
     368             : 
     369        1331 :   if (crypto_digest(digest_out, buf, len) < 0)
     370           0 :     goto done;
     371             : 
     372             :   rv = 0;
     373        1333 :   done:
     374        1333 :   tor_free(buf);
     375        1333 :   return rv;
     376             : }
     377             : 
     378             : /** Compute all digests of the DER encoding of <b>pk</b>, and store them
     379             :  * in <b>digests_out</b>.  Return 0 on success, -1 on failure. */
     380             : int
     381         564 : crypto_pk_get_common_digests(crypto_pk_t *pk, common_digests_t *digests_out)
     382             : {
     383         564 :   char *buf;
     384         564 :   size_t buflen;
     385         564 :   int len;
     386         564 :   int rv = -1;
     387             : 
     388         564 :   buflen = crypto_pk_keysize(pk)*2;
     389         564 :   buf = tor_malloc(buflen);
     390         564 :   len = crypto_pk_asn1_encode(pk, buf, buflen);
     391         564 :   if (len < 0)
     392           0 :     goto done;
     393             : 
     394         564 :   if (crypto_common_digests(digests_out, (char*)buf, len) < 0)
     395           1 :     goto done;
     396             : 
     397             :   rv = 0;
     398         564 :  done:
     399         564 :   tor_free(buf);
     400         564 :   return rv;
     401             : }
     402             : 
     403             : static const char RSA_PUBLIC_TAG[] = "RSA PUBLIC KEY";
     404             : static const char RSA_PRIVATE_TAG[] = "RSA PRIVATE KEY";
     405             : 
     406             : /* These are overestimates for how many extra bytes we might need to encode
     407             :  * a key in DER */
     408             : #define PRIVATE_ASN_MAX_OVERHEAD_FACTOR 16
     409             : #define PUBLIC_ASN_MAX_OVERHEAD_FACTOR 3
     410             : 
     411             : /** Helper: PEM-encode <b>env</b> and write it to a newly allocated string.
     412             :  * If <b>private_key</b>, write the private part of <b>env</b>; otherwise
     413             :  * write only the public portion. On success, set *<b>dest</b> to the new
     414             :  * string, *<b>len</b> to the string's length, and return 0.  On failure,
     415             :  * return -1.
     416             :  */
     417             : static int
     418         136 : crypto_pk_write_to_string_generic(crypto_pk_t *env,
     419             :                                   char **dest, size_t *len,
     420             :                                   bool private_key)
     421             : {
     422         272 :   const int factor =
     423             :     private_key ? PRIVATE_ASN_MAX_OVERHEAD_FACTOR
     424         136 :                 : PUBLIC_ASN_MAX_OVERHEAD_FACTOR;
     425         136 :   size_t buflen = crypto_pk_keysize(env) * factor;
     426         272 :   const char *tag =
     427         136 :     private_key ? RSA_PRIVATE_TAG : RSA_PUBLIC_TAG;
     428         136 :   char *buf = tor_malloc(buflen);
     429         136 :   char *result = NULL;
     430         136 :   size_t resultlen = 0;
     431         136 :   int rv = -1;
     432             : 
     433         272 :   int n = private_key
     434          30 :     ? crypto_pk_asn1_encode_private(env, buf, buflen)
     435         136 :     : crypto_pk_asn1_encode(env, buf, buflen);
     436         136 :   if (n < 0)
     437           0 :     goto done;
     438             : 
     439         136 :   resultlen = pem_encoded_size(n, tag);
     440         136 :   result = tor_malloc(resultlen);
     441         136 :   if (pem_encode(result, resultlen,
     442             :                  (const unsigned char *)buf, n, tag) < 0) {
     443           0 :     goto done;
     444             :   }
     445             : 
     446         136 :   *dest = result;
     447         136 :   *len = resultlen;
     448         136 :   rv = 0;
     449             : 
     450         136 :  done:
     451         136 :   if (rv < 0 && result) {
     452           0 :     memwipe(result, 0, resultlen);
     453           0 :     tor_free(result);
     454             :   }
     455         136 :   memwipe(buf, 0, buflen);
     456         136 :   tor_free(buf);
     457         136 :   return rv;
     458             : }
     459             : 
     460             : /** PEM-encode the public key portion of <b>env</b> and write it to a
     461             :  * newly allocated string.  On success, set *<b>dest</b> to the new
     462             :  * string, *<b>len</b> to the string's length, and return 0.  On
     463             :  * failure, return -1.
     464             :  */
     465             : int
     466         106 : crypto_pk_write_public_key_to_string(crypto_pk_t *env,
     467             :                                      char **dest, size_t *len)
     468             : {
     469         106 :   return crypto_pk_write_to_string_generic(env, dest, len, false);
     470             : }
     471             : 
     472             : /** PEM-encode the private key portion of <b>env</b> and write it to a
     473             :  * newly allocated string.  On success, set *<b>dest</b> to the new
     474             :  * string, *<b>len</b> to the string's length, and return 0.  On
     475             :  * failure, return -1.
     476             :  */
     477             : int
     478          30 : crypto_pk_write_private_key_to_string(crypto_pk_t *env,
     479             :                                           char **dest, size_t *len)
     480             : {
     481          30 :   return crypto_pk_write_to_string_generic(env, dest, len, true);
     482             : }
     483             : 
     484             : /**
     485             :  * Helper. Read a PEM-encoded RSA from the first <b>len</b> characters of
     486             :  * <b>src</b>, and store the result in <b>env</b>.  If <b>private_key</b>,
     487             :  * expect a private key; otherwise expect a public key. Return 0 on success,
     488             :  * -1 on failure.  If len is -1, the string is nul-terminated.
     489             :  */
     490             : static int
     491       41051 : crypto_pk_read_from_string_generic(crypto_pk_t *env, const char *src,
     492             :                                    size_t len, int severity,
     493             :                                    bool private_key, int max_bits)
     494             : {
     495       41051 :   if (len == (size_t)-1) // "-1" indicates "use the length of the string."
     496          27 :     len = strlen(src);
     497             : 
     498       41051 :   const char *ktype = private_key ? "private key" : "public key";
     499       82102 :   const char *tag =
     500       41051 :     private_key ? RSA_PRIVATE_TAG : RSA_PUBLIC_TAG;
     501       41051 :   size_t buflen = len;
     502       41051 :   uint8_t *buf = tor_malloc(buflen);
     503       41051 :   int rv = -1;
     504             : 
     505       41051 :   int n = pem_decode(buf, buflen, src, len, tag);
     506       41051 :   if (n < 0) {
     507           3 :     log_fn(severity, LD_CRYPTO,
     508             :            "Error decoding PEM wrapper while reading %s", ktype);
     509           3 :     goto done;
     510             :   }
     511             : 
     512       82096 :   crypto_pk_t *pk = private_key
     513       41030 :     ? crypto_pk_asn1_decode_private((const char*)buf, n, max_bits)
     514       41048 :     : crypto_pk_asn1_decode((const char*)buf, n);
     515       41048 :   if (! pk) {
     516           1 :     log_fn(severity, LD_CRYPTO,
     517             :            "Error decoding ASN.1 while reading %s", ktype);
     518           1 :     goto done;
     519             :   }
     520             : 
     521       41047 :   if (private_key)
     522       41029 :     crypto_pk_assign_private(env, pk);
     523             :   else
     524          18 :     crypto_pk_assign_public(env, pk);
     525       41047 :   crypto_pk_free(pk);
     526       41047 :   rv = 0;
     527             : 
     528       41051 :  done:
     529       41051 :   memwipe(buf, 0, buflen);
     530       41051 :   tor_free(buf);
     531       41051 :   return rv;
     532             : }
     533             : 
     534             : /** Read a PEM-encoded public key from the first <b>len</b> characters of
     535             :  * <b>src</b>, and store the result in <b>env</b>.  Return 0 on success, -1 on
     536             :  * failure.  If len is -1, the string is nul-terminated.
     537             :  */
     538             : int
     539          19 : crypto_pk_read_public_key_from_string(crypto_pk_t *env,
     540             :                                       const char *src, size_t len)
     541             : {
     542          19 :   return crypto_pk_read_from_string_generic(env, src, len, LOG_INFO, false,
     543             :                                             -1);
     544             : }
     545             : 
     546             : /** Read a PEM-encoded private key from the <b>len</b>-byte string <b>src</b>
     547             :  * into <b>env</b>.  Return 0 on success, -1 on failure.  If len is -1,
     548             :  * the string is nul-terminated.
     549             :  */
     550             : int
     551       41016 : crypto_pk_read_private_key_from_string(crypto_pk_t *env,
     552             :                                        const char *src, ssize_t len)
     553             : {
     554       41016 :   return crypto_pk_read_from_string_generic(env, src, len, LOG_INFO, true,
     555             :                                             -1);
     556             : }
     557             : 
     558             : /**
     559             :  * As crypto_pk_read_private_key_from_string(), but reject any key
     560             :  * with a modulus longer than 1024 bits before doing any expensive
     561             :  * validation on it.
     562             :  */
     563             : int
     564           0 : crypto_pk_read_private_key1024_from_string(crypto_pk_t *env,
     565             :                                            const char *src, ssize_t len)
     566             : {
     567           0 :   return crypto_pk_read_from_string_generic(env, src, len, LOG_INFO, true,
     568             :                                             1024);
     569             : }
     570             : 
     571             : /** If a file is longer than this, we won't try to decode its private key */
     572             : #define MAX_PRIVKEY_FILE_LEN (16*1024*1024)
     573             : 
     574             : /** Read a PEM-encoded private key from the file named by
     575             :  * <b>keyfile</b> into <b>env</b>.  Return 0 on success, -1 on failure.
     576             :  */
     577             : int
     578          17 : crypto_pk_read_private_key_from_filename(crypto_pk_t *env,
     579             :                                          const char *keyfile)
     580             : {
     581          17 :   struct stat st;
     582          17 :   char *buf = read_file_to_str(keyfile, 0, &st);
     583          17 :   if (!buf) {
     584           1 :     log_warn(LD_CRYPTO, "Unable to read file for private key in %s",
     585             :              escaped(keyfile));
     586           1 :     return -1;
     587             :   }
     588          16 :   if (st.st_size > MAX_PRIVKEY_FILE_LEN) {
     589           0 :     log_warn(LD_CRYPTO, "Private key file %s was far too large.",
     590             :              escaped(keyfile));
     591           0 :     tor_free(buf);
     592           0 :     return -1;
     593             :   }
     594             : 
     595          16 :   int rv = crypto_pk_read_from_string_generic(env, buf, (ssize_t)st.st_size,
     596             :                                               LOG_WARN, true, -1);
     597          16 :   if (rv < 0) {
     598           1 :     log_warn(LD_CRYPTO, "Unable to decode private key from file %s",
     599             :              escaped(keyfile));
     600             :   }
     601          16 :   memwipe(buf, 0, (size_t)st.st_size);
     602          16 :   tor_free(buf);
     603          16 :   return rv;
     604             : }
     605             : 
     606             : /** Write the private key from <b>env</b> into the file named by <b>fname</b>,
     607             :  * PEM-encoded.  Return 0 on success, -1 on failure.
     608             :  */
     609             : int
     610          30 : crypto_pk_write_private_key_to_filename(crypto_pk_t *env,
     611             :                                         const char *fname)
     612             : {
     613          30 :   char *s = NULL;
     614          30 :   size_t n = 0;
     615             : 
     616          30 :   if (crypto_pk_write_private_key_to_string(env, &s, &n) < 0)
     617             :     return -1;
     618             : 
     619          30 :   int rv = write_bytes_to_file(fname, s, n, 0);
     620          30 :   memwipe(s, 0, n);
     621          30 :   tor_free(s);
     622          30 :   return rv;
     623             : }
     624             : 
     625             : /** Given a crypto_pk_t <b>pk</b>, allocate a new buffer containing the
     626             :  * Base64 encoding of the DER representation of the private key as a NUL
     627             :  * terminated string, and return it via <b>priv_out</b>.  Return 0 on
     628             :  * success, -1 on failure.
     629             :  *
     630             :  * It is the caller's responsibility to sanitize and free the resulting buffer.
     631             :  */
     632             : int
     633           1 : crypto_pk_base64_encode_private(const crypto_pk_t *pk, char **priv_out)
     634             : {
     635           1 :   size_t buflen = crypto_pk_keysize(pk)*16;
     636           1 :   char *buf = tor_malloc(buflen);
     637           1 :   char *result = NULL;
     638           1 :   size_t reslen = 0;
     639           1 :   bool ok = false;
     640             : 
     641           1 :   int n = crypto_pk_asn1_encode_private(pk, buf, buflen);
     642             : 
     643           1 :   if (n < 0)
     644           0 :     goto done;
     645             : 
     646           1 :   reslen = base64_encode_size(n, 0)+1;
     647           1 :   result = tor_malloc(reslen);
     648           1 :   if (base64_encode(result, reslen, buf, n, 0) < 0)
     649           0 :     goto done;
     650             : 
     651             :   ok = true;
     652             : 
     653           1 :  done:
     654           1 :   memwipe(buf, 0, buflen);
     655           1 :   tor_free(buf);
     656           1 :   if (result && ! ok) {
     657           0 :     memwipe(result, 0, reslen);
     658           0 :     tor_free(result);
     659             :   }
     660           1 :   *priv_out = result;
     661           1 :   return ok ? 0 : -1;
     662             : }
     663             : 
     664             : /** Given a string containing the Base64 encoded DER representation of the
     665             :  * private key <b>str</b>, decode and return the result on success, or NULL
     666             :  * on failure.
     667             :  */
     668             : crypto_pk_t *
     669           3 : crypto_pk_base64_decode_private(const char *str, size_t len)
     670             : {
     671           3 :   crypto_pk_t *pk = NULL;
     672             : 
     673           3 :   char *der = tor_malloc_zero(len + 1);
     674           3 :   int der_len = base64_decode(der, len, str, len);
     675           3 :   if (der_len <= 0) {
     676           1 :     log_warn(LD_CRYPTO, "Stored RSA private key seems corrupted (base64).");
     677           1 :     goto out;
     678             :   }
     679             : 
     680           2 :   pk = crypto_pk_asn1_decode_private(der, der_len, -1);
     681             : 
     682           3 :  out:
     683           3 :   memwipe(der, 0, len+1);
     684           3 :   tor_free(der);
     685             : 
     686           3 :   return pk;
     687             : }

Generated by: LCOV version 1.14