tor

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

x509_nss.c (13865B)


      1 /* Copyright (c) 2003, Roger Dingledine.
      2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      4 /* See LICENSE for licensing information */
      5 
      6 /**
      7 * \file x509_nss.c
      8 * \brief Wrapper functions to present a consistent interface to
      9 * X.509 functions from NSS.
     10 **/
     11 
     12 #define TOR_X509_PRIVATE
     13 #include "lib/tls/x509.h"
     14 #include "lib/tls/x509_internal.h"
     15 #include "lib/tls/tortls.h"
     16 #include "lib/crypt_ops/crypto_rand.h"
     17 #include "lib/crypt_ops/crypto_util.h"
     18 #include "lib/crypt_ops/crypto_nss_mgt.h"
     19 #include "lib/log/util_bug.h"
     20 #include "lib/encoding/time_fmt.h"
     21 #include "lib/string/printf.h"
     22 
     23 DISABLE_GCC_WARNING("-Wstrict-prototypes")
     24 #include <pk11pub.h>
     25 #include <cryptohi.h>
     26 #include <cert.h>
     27 #include <keyhi.h>
     28 #include <time.h>
     29 ENABLE_GCC_WARNING("-Wstrict-prototypes")
     30 
     31 /* Units of PRTime per second.
     32 *
     33 * (PRTime is based in microseconds since the Unix
     34 * epoch.) */
     35 #define PRTIME_PER_SEC (1000*1000)
     36 
     37 static tor_x509_cert_impl_t *tor_x509_cert_decode_internal(
     38                      const uint8_t *certificate, int certificate_len);
     39 
     40 static tor_x509_cert_impl_t *
     41 tor_tls_create_certificate_internal(crypto_pk_t *rsa,
     42                                    crypto_pk_t *rsa_sign,
     43                                    CERTName *subject_dn,
     44                                    CERTName *issuer_dn,
     45                                    time_t start_time,
     46                                    time_t end_time)
     47 {
     48  if (! crypto_pk_key_is_private(rsa_sign)) {
     49    return NULL;
     50  }
     51 
     52  const SECKEYPublicKey *subject_key = crypto_pk_get_nss_pubkey(rsa);
     53  const SECKEYPrivateKey *signing_key = crypto_pk_get_nss_privkey(rsa_sign);
     54  SECStatus s;
     55 
     56  CERTSubjectPublicKeyInfo *subject_spki = NULL;
     57  CERTCertificateRequest *request = NULL;
     58  CERTValidity *validity = NULL;
     59  CERTCertificate *cert = NULL;
     60  SECItem der = { .data = NULL, .len = 0 };
     61  SECItem signed_der = { .data = NULL, .len = 0 };
     62 
     63  CERTCertificate *result_cert = NULL;
     64 
     65  validity = CERT_CreateValidity(((PRTime)start_time) * PRTIME_PER_SEC,
     66                                 ((PRTime)end_time) * PRTIME_PER_SEC);
     67  if (BUG(! validity)) {
     68    /* LCOV_EXCL_START */
     69    crypto_nss_log_errors(LOG_WARN, "creating a validity object");
     70    goto err;
     71    /* LCOV_EXCL_STOP */
     72  }
     73 
     74  unsigned long serial_number;
     75  crypto_rand((char*)&serial_number, sizeof(serial_number));
     76 
     77  subject_spki = SECKEY_CreateSubjectPublicKeyInfo(subject_key);
     78  if (!subject_spki)
     79    goto err;
     80 
     81  /* Make a CSR ... */
     82  // XXX do we need to set any attributes?
     83  request = CERT_CreateCertificateRequest(subject_dn,
     84                                          subject_spki,
     85                                          NULL /* attributes */);
     86  if (!request)
     87    goto err;
     88 
     89  /* Put it into a certificate ... */
     90  cert = CERT_CreateCertificate(serial_number,
     91                                issuer_dn,
     92                                validity,
     93                                request);
     94  if (!cert)
     95    goto err;
     96 
     97  /* version 3 cert */
     98  *cert->version.data = 2; /* 2 means version 3. */
     99  cert->version.len = 1;
    100 
    101  // XXX do we need to set anything else on the cert?
    102 
    103  /* Sign it. */
    104  KeyType privkey_type = SECKEY_GetPrivateKeyType(signing_key);
    105  SECOidTag oid_tag = SEC_GetSignatureAlgorithmOidTag(privkey_type,
    106                                                      SEC_OID_SHA256);
    107  if (oid_tag == SEC_OID_UNKNOWN)
    108    goto err;
    109  s = SECOID_SetAlgorithmID(cert->arena, &cert->signature, oid_tag, NULL);
    110  if (s != SECSuccess)
    111    goto err;
    112 
    113  void *tmp;
    114  tmp = SEC_ASN1EncodeItem(cert->arena, &der, cert,
    115                           SEC_ASN1_GET(CERT_CertificateTemplate));
    116  if (!tmp)
    117    goto err;
    118 
    119 #if 0
    120  s = SEC_DerSignDataWithAlgorithmID(cert->arena,
    121                                     &signed_der,
    122                                     der.data, der.len,
    123                                     (SECKEYPrivateKey *)signing_key,//const
    124                                     &cert->signature);
    125 #else /* !(0) */
    126  s = SEC_DerSignData(cert->arena,
    127                      &signed_der,
    128                      der.data, der.len,
    129                      (SECKEYPrivateKey *)signing_key,//const
    130                      SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION);
    131 #endif /* 0 */
    132 
    133  if (s != SECSuccess)
    134    goto err;
    135 
    136  /* Re-parse it, to make sure all the certificates we actually use
    137   * appear via being decoded. */
    138  result_cert = tor_x509_cert_decode_internal(signed_der.data, signed_der.len);
    139 
    140 #if 1
    141  {
    142    // Can we check the cert we just signed?
    143    tor_assert(result_cert);
    144    SECKEYPublicKey *issuer_pk = (SECKEYPublicKey *)
    145      crypto_pk_get_nss_pubkey(rsa_sign);
    146    SECStatus cert_ok = CERT_VerifySignedDataWithPublicKey(
    147                               &result_cert->signatureWrap, issuer_pk, NULL);
    148    tor_assert(cert_ok == SECSuccess);
    149  }
    150 #endif /* 1 */
    151 
    152 err:
    153  if (subject_spki)
    154    SECKEY_DestroySubjectPublicKeyInfo(subject_spki);
    155  if (request)
    156    CERT_DestroyCertificateRequest(request);
    157  if (validity)
    158    CERT_DestroyValidity(validity);
    159 
    160  // unnecessary, since these are allocated in the cert's arena.
    161  //SECITEM_FreeItem(&der, PR_FALSE);
    162  //SECITEM_FreeItem(&signed_der, PR_FALSE);
    163  if (cert)
    164    CERT_DestroyCertificate(cert);
    165 
    166  return result_cert;
    167 }
    168 
    169 MOCK_IMPL(tor_x509_cert_impl_t *,
    170 tor_tls_create_certificate,(crypto_pk_t *rsa,
    171                            crypto_pk_t *rsa_sign,
    172                            const char *cname,
    173                            const char *cname_sign,
    174                            unsigned int cert_lifetime))
    175 {
    176  tor_assert(rsa);
    177  tor_assert(rsa_sign);
    178  tor_assert(cname);
    179  tor_assert(cname_sign);
    180 
    181  char *cname_rfc_1485 = NULL, *cname_sign_rfc_1485 = NULL;
    182  CERTName *subject_dn = NULL, *issuer_dn = NULL;
    183  time_t start_time;
    184  time_t end_time;
    185  CERTCertificate *result = NULL;
    186 
    187  tor_asprintf(&cname_rfc_1485, "CN=%s", cname);
    188  tor_asprintf(&cname_sign_rfc_1485, "CN=%s", cname_sign);
    189 
    190  subject_dn = CERT_AsciiToName(cname_rfc_1485);
    191  issuer_dn = CERT_AsciiToName(cname_sign_rfc_1485);
    192  if (!subject_dn || !issuer_dn)
    193    goto err;
    194 
    195  tor_tls_pick_certificate_lifetime(time(NULL), cert_lifetime,
    196                                    &start_time, &end_time);
    197 
    198  result = tor_tls_create_certificate_internal(rsa,
    199                                               rsa_sign,
    200                                               subject_dn,
    201                                               issuer_dn,
    202                                               start_time,
    203                                               end_time);
    204 err:
    205  tor_free(cname_rfc_1485);
    206  tor_free(cname_sign_rfc_1485);
    207  if (subject_dn)
    208    CERT_DestroyName(subject_dn);
    209  if (issuer_dn)
    210    CERT_DestroyName(issuer_dn);
    211 
    212  return result;
    213 }
    214 
    215 /** Set *<b>encoded_out</b> and *<b>size_out</b> to <b>cert</b>'s encoded DER
    216 * representation and length, respectively. */
    217 void
    218 tor_x509_cert_get_der(const tor_x509_cert_t *cert,
    219                 const uint8_t **encoded_out, size_t *size_out)
    220 {
    221  tor_assert(cert);
    222  tor_assert(cert->cert);
    223  tor_assert(encoded_out);
    224  tor_assert(size_out);
    225 
    226  const SECItem *item = &cert->cert->derCert;
    227  *encoded_out = item->data;
    228  *size_out = (size_t)item->len;
    229 }
    230 
    231 void
    232 tor_x509_cert_impl_free_(tor_x509_cert_impl_t *cert)
    233 {
    234  if (cert)
    235    CERT_DestroyCertificate(cert);
    236 }
    237 
    238 tor_x509_cert_impl_t *
    239 tor_x509_cert_impl_dup_(tor_x509_cert_impl_t *cert)
    240 {
    241  if (cert)
    242    return CERT_DupCertificate(cert);
    243  else
    244    return NULL;
    245 }
    246 
    247 /**
    248 * As tor_x509_cert_decode, but return the NSS certificate type
    249 */
    250 static tor_x509_cert_impl_t *
    251 tor_x509_cert_decode_internal(const uint8_t *certificate,
    252                              int certificate_len)
    253 {
    254  tor_assert(certificate);
    255  if (certificate_len > INT_MAX)
    256    return NULL;
    257 
    258  SECItem der = { .type = siBuffer,
    259                  .data = (unsigned char *)certificate,
    260                  .len = certificate_len };
    261  CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
    262  tor_assert(certdb);
    263  return CERT_NewTempCertificate(certdb,
    264                                 &der,
    265                                 NULL /* nickname */,
    266                                 PR_FALSE, /* isPerm */
    267                                 PR_TRUE /* CopyDER */);
    268 }
    269 
    270 tor_x509_cert_t *
    271 tor_x509_cert_decode(const uint8_t *certificate,
    272                     size_t certificate_len)
    273 {
    274  CERTCertificate *cert = tor_x509_cert_decode_internal(certificate,
    275                                                        (int)certificate_len);
    276  if (! cert) {
    277    crypto_nss_log_errors(LOG_INFO, "decoding certificate");
    278    return NULL;
    279  }
    280 
    281  tor_x509_cert_t *newcert = tor_x509_cert_new(cert);
    282 
    283  return newcert;
    284 }
    285 
    286 crypto_pk_t *
    287 tor_tls_cert_get_key(tor_x509_cert_t *cert)
    288 {
    289  tor_assert(cert);
    290  CERTSubjectPublicKeyInfo *spki = &cert->cert->subjectPublicKeyInfo;
    291  SECKEYPublicKey *pub = SECKEY_ExtractPublicKey(spki); // we own this pointer
    292  if (pub == NULL)
    293    return NULL;
    294 
    295  if (SECKEY_GetPublicKeyType(pub) != rsaKey) {
    296    SECKEY_DestroyPublicKey(pub);
    297    return NULL;
    298  }
    299 
    300  return crypto_pk_new_from_nss_pubkey(pub);
    301 }
    302 
    303 int
    304 tor_tls_cert_is_valid(int severity,
    305                      const tor_x509_cert_t *cert,
    306                      const tor_x509_cert_t *signing_cert,
    307                      time_t now,
    308                      int check_rsa_1024)
    309 {
    310  int result = 0;
    311 
    312  tor_assert(cert);
    313  tor_assert(signing_cert);
    314 
    315  SECKEYPublicKey *pk = CERT_ExtractPublicKey(signing_cert->cert);
    316  if (pk == NULL) {
    317    log_fn(severity, LD_CRYPTO,
    318           "Invalid certificate: could not extract issuer key");
    319    goto fail;
    320  }
    321 
    322  SECStatus s = CERT_VerifySignedDataWithPublicKey(&cert->cert->signatureWrap,
    323                                                   pk, NULL);
    324  if (s != SECSuccess) {
    325    log_fn(severity, LD_CRYPTO,
    326           "Invalid certificate: could not validate signature.");
    327    goto fail;
    328  }
    329 
    330  if (tor_x509_check_cert_lifetime_internal(severity,
    331                                            cert->cert,
    332                                            now,
    333                                            TOR_X509_PAST_SLOP,
    334                                            TOR_X509_FUTURE_SLOP) < 0)
    335    goto fail;
    336 
    337  if (check_rsa_1024) {
    338    /* We require that this is a 1024-bit RSA key, for legacy reasons .:p */
    339    if (SECKEY_GetPublicKeyType(pk) != rsaKey ||
    340        SECKEY_PublicKeyStrengthInBits(pk) != 1024) {
    341      log_fn(severity, LD_CRYPTO, "Invalid certificate: Key is not RSA1024.");
    342      goto fail;
    343    }
    344  } else {
    345    /* We require that this key is at least minimally strong. */
    346    unsigned min_bits = (SECKEY_GetPublicKeyType(pk) == ecKey) ? 128: 1024;
    347    if (SECKEY_PublicKeyStrengthInBits(pk) < min_bits) {
    348      log_fn(severity, LD_CRYPTO, "Invalid certificate: Key is too weak.");
    349      goto fail;
    350    }
    351  }
    352 
    353  /* The certificate is valid. */
    354  result = 1;
    355 
    356 fail:
    357  if (pk)
    358    SECKEY_DestroyPublicKey(pk);
    359  return result;
    360 }
    361 
    362 static void
    363 log_cert_lifetime(int severity,
    364                  const char *status,
    365                  time_t now,
    366                  PRTime notBefore,
    367                  PRTime notAfter)
    368 {
    369  log_fn(severity, LD_GENERAL,
    370         "Certificate %s. Either their clock is set wrong, or your clock "
    371         "is incorrect.", status);
    372 
    373  char nowbuf[ISO_TIME_LEN+1];
    374  char nbbuf[ISO_TIME_LEN+1];
    375  char nabuf[ISO_TIME_LEN+1];
    376 
    377  format_iso_time(nowbuf, now);
    378  format_iso_time(nbbuf, notBefore / PRTIME_PER_SEC);
    379  format_iso_time(nabuf, notAfter / PRTIME_PER_SEC);
    380 
    381  log_fn(severity, LD_GENERAL,
    382         "(The certificate is valid from %s until %s. Your time is %s.)",
    383         nbbuf, nabuf, nowbuf);
    384 }
    385 
    386 int
    387 tor_x509_check_cert_lifetime_internal(int severity,
    388                                      const tor_x509_cert_impl_t *cert,
    389                                      time_t now,
    390                                      int past_tolerance,
    391                                      int future_tolerance)
    392 {
    393  tor_assert(cert);
    394 
    395  PRTime notBefore=0, notAfter=0;
    396  int64_t t;
    397  SECStatus r = CERT_GetCertTimes(cert, &notBefore, &notAfter);
    398  if (r != SECSuccess) {
    399    log_fn(severity, LD_CRYPTO,
    400           "Couldn't get validity times from certificate");
    401    return -1;
    402  }
    403 
    404  t = ((int64_t)now) + future_tolerance;
    405  t *= PRTIME_PER_SEC;
    406  if (notBefore > t) {
    407    log_cert_lifetime(severity, "not yet valid", now,
    408                      notBefore, notAfter);
    409    return -1;
    410  }
    411 
    412  t = ((int64_t)now) - past_tolerance;
    413  t *= PRTIME_PER_SEC;
    414  if (notAfter < t) {
    415    log_cert_lifetime(severity, "already expired", now,
    416                      notBefore, notAfter);
    417    return -1;
    418  }
    419 
    420  return 0;
    421 }
    422 
    423 #ifdef TOR_UNIT_TESTS
    424 tor_x509_cert_t *
    425 tor_x509_cert_replace_expiration(const tor_x509_cert_t *inp,
    426                                 time_t new_expiration_time,
    427                                 crypto_pk_t *signing_key)
    428 {
    429  tor_assert(inp);
    430  tor_assert(signing_key);
    431 
    432  PRTime notBefore=0, notAfter=0;
    433  SECStatus r = CERT_GetCertTimes(inp->cert, &notBefore, &notAfter);
    434  if (r != SECSuccess)
    435    return NULL;
    436 
    437  time_t start_time = notBefore / PRTIME_PER_SEC;
    438  if (new_expiration_time < start_time) {
    439    /* This prevents an NSS error. */
    440    start_time = new_expiration_time - 10;
    441  }
    442 
    443  crypto_pk_t *subject_key = tor_tls_cert_get_key((tor_x509_cert_t *)inp);
    444  if (!subject_key)
    445    return NULL;
    446 
    447  CERTCertificate *newcert;
    448 
    449  newcert = tor_tls_create_certificate_internal(subject_key,
    450                                                signing_key,
    451                                                &inp->cert->subject,
    452                                                &inp->cert->issuer,
    453                                                start_time,
    454                                                new_expiration_time);
    455 
    456  crypto_pk_free(subject_key);
    457 
    458  return newcert ? tor_x509_cert_new(newcert) : NULL;
    459 }
    460 #endif /* defined(TOR_UNIT_TESTS) */