Tor 0.4.9.0-alpha-dev
x509_nss.c
Go to the documentation of this file.
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"
19#include "lib/log/util_bug.h"
21#include "lib/string/printf.h"
22
23DISABLE_GCC_WARNING("-Wstrict-prototypes")
24#include <pk11pub.h>
25#include <cryptohi.h>
26#include <cert.h>
27#include <keyhi.h>
28#include <time.h>
29ENABLE_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
37static tor_x509_cert_impl_t *tor_x509_cert_decode_internal(
38 const uint8_t *certificate, int certificate_len);
39
40static tor_x509_cert_impl_t *
41tor_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
169MOCK_IMPL(tor_x509_cert_impl_t *,
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. */
217void
218tor_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
231void
232tor_x509_cert_impl_free_(tor_x509_cert_impl_t *cert)
233{
234 if (cert)
235 CERT_DestroyCertificate(cert);
236}
237
238tor_x509_cert_impl_t *
239tor_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*/
250static tor_x509_cert_impl_t *
251tor_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
270tor_x509_cert_t *
271tor_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
287tor_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
303int
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
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
362static void
363log_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
386int
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
424tor_x509_cert_t *
425tor_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) */
Headers for crypto_nss_mgt.c.
void crypto_rand(char *to, size_t n)
Definition: crypto_rand.c:479
Common functions for using (pseudo-)random number generators.
int crypto_pk_key_is_private(const crypto_pk_t *key)
Common functions for cryptographic routines.
#define log_fn(severity, domain, args,...)
Definition: log.h:283
#define LD_CRYPTO
Definition: log.h:64
#define LD_GENERAL
Definition: log.h:62
#define LOG_WARN
Definition: log.h:53
#define LOG_INFO
Definition: log.h:45
#define tor_free(p)
Definition: malloc.h:56
int tor_asprintf(char **strp, const char *fmt,...)
Definition: printf.c:75
Header for printf.c.
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
Definitions for timing-related constants.
void format_iso_time(char *buf, time_t t)
Definition: time_fmt.c:326
Header for time_fmt.c.
Headers for tortls.c.
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:103
Headers for tortls.c.
crypto_pk_t * tor_tls_cert_get_key(tor_x509_cert_t *cert)
Definition: x509_nss.c:287
tor_x509_cert_t * tor_x509_cert_decode(const uint8_t *certificate, size_t certificate_len)
Definition: x509_nss.c:271
int tor_tls_cert_is_valid(int severity, const tor_x509_cert_t *cert, const tor_x509_cert_t *signing_cert, time_t now, int check_rsa_1024)
Definition: x509_nss.c:304
static tor_x509_cert_impl_t * tor_x509_cert_decode_internal(const uint8_t *certificate, int certificate_len)
Definition: x509_nss.c:251
void tor_x509_cert_get_der(const tor_x509_cert_t *cert, const uint8_t **encoded_out, size_t *size_out)
Definition: x509_nss.c:218
int tor_x509_check_cert_lifetime_internal(int severity, const X509 *cert, time_t now, int past_tolerance, int future_tolerance)
Definition: x509_openssl.c:428
X509 * tor_tls_create_certificate(crypto_pk_t *rsa, crypto_pk_t *rsa_sign, const char *cname, const char *cname_sign, unsigned int cert_lifetime)
Definition: x509_openssl.c:105
static void log_cert_lifetime(int severity, const X509 *cert, const char *problem, time_t now)
Definition: x509_openssl.c:367