Update copyrights to 2021, using "make update-copyright"
[tor.git] / src / feature / nodelist / torcert.c
blobab3c0ecc1bb9e0af4d4a8f031842fb106eae7cfd
1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file torcert.c
7 * \brief Implementation for ed25519-signed certificates as used in the Tor
8 * protocol.
10 * This certificate format is designed to be simple and compact; it's
11 * documented in tor-spec.txt in the torspec.git repository. All of the
12 * certificates in this format are signed with an Ed25519 key; the
13 * contents themselves may be another Ed25519 key, a digest of a
14 * RSA key, or some other material.
16 * In this module there is also support for a crooss-certification of
17 * Ed25519 identities using (older) RSA1024 identities.
19 * Tor uses other types of certificate too, beyond those described in this
20 * module. Notably, our use of TLS requires us to touch X.509 certificates,
21 * even though sensible people would stay away from those. Our X.509
22 * certificates are represented with tor_x509_cert_t, and implemented in
23 * tortls.c. We also have a separate certificate type that authorities
24 * use to authenticate their RSA signing keys with their RSA identity keys:
25 * that one is authority_cert_t, and it's mostly handled in routerlist.c.
28 #include "core/or/or.h"
29 #include "app/config/config.h"
30 #include "lib/crypt_ops/crypto_util.h"
31 #include "feature/nodelist/torcert.h"
32 #include "trunnel/ed25519_cert.h"
33 #include "lib/log/log.h"
34 #include "trunnel/link_handshake.h"
35 #include "lib/tls/tortls.h"
36 #include "lib/tls/x509.h"
38 #include "core/or/or_handshake_certs_st.h"
40 /** As tor_cert_create(), but accept an arbitrary signed_key_type as the
41 * subject key -- not just an ed25519 key.
43 tor_cert_t *
44 tor_cert_create_raw(const ed25519_keypair_t *signing_key,
45 uint8_t cert_type,
46 uint8_t signed_key_type,
47 const uint8_t signed_key_info[32],
48 time_t now, time_t lifetime,
49 uint32_t flags)
51 tor_cert_t *torcert = NULL;
53 ed25519_cert_t *cert = ed25519_cert_new();
54 tor_assert(cert); // Unlike Tor's, Trunnel's "new" functions can return NULL.
55 cert->cert_type = cert_type;
56 cert->exp_field = (uint32_t) CEIL_DIV(now + lifetime, 3600);
57 cert->cert_key_type = signed_key_type;
58 memcpy(cert->certified_key, signed_key_info, 32);
60 if (flags & CERT_FLAG_INCLUDE_SIGNING_KEY) {
61 ed25519_cert_extension_t *ext = ed25519_cert_extension_new();
62 ext->ext_type = CERTEXT_SIGNED_WITH_KEY;
63 memcpy(ext->un_signing_key, signing_key->pubkey.pubkey, 32);
64 ed25519_cert_add_ext(cert, ext);
65 ++cert->n_extensions;
68 const ssize_t alloc_len = ed25519_cert_encoded_len(cert);
69 tor_assert(alloc_len > 0);
70 uint8_t *encoded = tor_malloc(alloc_len);
71 const ssize_t real_len = ed25519_cert_encode(encoded, alloc_len, cert);
72 if (real_len < 0)
73 goto err;
74 tor_assert(real_len == alloc_len);
75 tor_assert(real_len > ED25519_SIG_LEN);
76 uint8_t *sig = encoded + (real_len - ED25519_SIG_LEN);
77 tor_assert(fast_mem_is_zero((char*)sig, ED25519_SIG_LEN));
79 ed25519_signature_t signature;
80 if (ed25519_sign(&signature, encoded,
81 real_len-ED25519_SIG_LEN, signing_key)<0) {
82 /* LCOV_EXCL_START */
83 log_warn(LD_BUG, "Can't sign certificate");
84 goto err;
85 /* LCOV_EXCL_STOP */
87 memcpy(sig, signature.sig, ED25519_SIG_LEN);
89 torcert = tor_cert_parse(encoded, real_len);
90 if (! torcert) {
91 /* LCOV_EXCL_START */
92 log_warn(LD_BUG, "Generated a certificate we cannot parse");
93 goto err;
94 /* LCOV_EXCL_STOP */
97 if (tor_cert_checksig(torcert, &signing_key->pubkey, now) < 0) {
98 /* LCOV_EXCL_START */
99 log_warn(LD_BUG, "Generated a certificate whose signature we can't "
100 "check: %s", tor_cert_describe_signature_status(torcert));
101 goto err;
102 /* LCOV_EXCL_STOP */
105 tor_free(encoded);
107 goto done;
109 /* LCOV_EXCL_START */
110 err:
111 tor_cert_free(torcert);
112 torcert = NULL;
113 /* LCOV_EXCL_STOP */
115 done:
116 ed25519_cert_free(cert);
117 tor_free(encoded);
118 return torcert;
122 * Create and return a new new certificate of type <b>cert_type</b> to
123 * authenticate <b>signed_key</b> using the key <b>signing_key</b>. The
124 * certificate should remain valid for at least <b>lifetime</b> seconds after
125 * <b>now</b>.
127 * If CERT_FLAG_INCLUDE_SIGNING_KEY is set in <b>flags</b>, embed
128 * the public part of <b>signing_key</b> in the certificate.
130 tor_cert_t *
131 tor_cert_create_ed25519(const ed25519_keypair_t *signing_key,
132 uint8_t cert_type,
133 const ed25519_public_key_t *signed_key,
134 time_t now, time_t lifetime,
135 uint32_t flags)
137 return tor_cert_create_raw(signing_key, cert_type,
138 SIGNED_KEY_TYPE_ED25519, signed_key->pubkey,
139 now, lifetime, flags);
142 /** Release all storage held for <b>cert</b>. */
143 void
144 tor_cert_free_(tor_cert_t *cert)
146 if (! cert)
147 return;
149 if (cert->encoded)
150 memwipe(cert->encoded, 0, cert->encoded_len);
151 tor_free(cert->encoded);
153 memwipe(cert, 0, sizeof(tor_cert_t));
154 tor_free(cert);
157 /** Parse a certificate encoded with <b>len</b> bytes in <b>encoded</b>. */
158 tor_cert_t *
159 tor_cert_parse(const uint8_t *encoded, const size_t len)
161 tor_cert_t *cert = NULL;
162 ed25519_cert_t *parsed = NULL;
163 ssize_t got_len = ed25519_cert_parse(&parsed, encoded, len);
164 if (got_len < 0 || (size_t) got_len != len)
165 goto err;
167 cert = tor_malloc_zero(sizeof(tor_cert_t));
168 cert->encoded = tor_memdup(encoded, len);
169 cert->encoded_len = len;
171 memcpy(cert->signed_key.pubkey, parsed->certified_key, 32);
172 int64_t valid_until_64 = ((int64_t)parsed->exp_field) * 3600;
173 #if SIZEOF_TIME_T < 8
174 if (valid_until_64 > TIME_MAX)
175 valid_until_64 = TIME_MAX - 1;
176 #endif
177 cert->valid_until = (time_t) valid_until_64;
178 cert->cert_type = parsed->cert_type;
180 for (unsigned i = 0; i < ed25519_cert_getlen_ext(parsed); ++i) {
181 ed25519_cert_extension_t *ext = ed25519_cert_get_ext(parsed, i);
182 if (ext->ext_type == CERTEXT_SIGNED_WITH_KEY) {
183 if (cert->signing_key_included)
184 goto err;
186 cert->signing_key_included = 1;
187 memcpy(cert->signing_key.pubkey, ext->un_signing_key, 32);
188 } else if (ext->ext_flags & CERTEXT_FLAG_AFFECTS_VALIDATION) {
189 /* Unrecognized extension with affects_validation set */
190 goto err;
194 goto done;
195 err:
196 tor_cert_free(cert);
197 cert = NULL;
198 done:
199 ed25519_cert_free(parsed);
200 return cert;
203 /** Fill in <b>checkable_out</b> with the information needed to check
204 * the signature on <b>cert</b> with <b>pubkey</b>.
206 * On success, if <b>expiration_out</b> is provided, and it is some time
207 * _after_ the expiration time of this certificate, set it to the
208 * expiration time of this certificate.
211 tor_cert_get_checkable_sig(ed25519_checkable_t *checkable_out,
212 const tor_cert_t *cert,
213 const ed25519_public_key_t *pubkey,
214 time_t *expiration_out)
216 if (! pubkey) {
217 if (cert->signing_key_included)
218 pubkey = &cert->signing_key;
219 else
220 return -1;
223 checkable_out->msg = cert->encoded;
224 checkable_out->pubkey = pubkey;
225 tor_assert(cert->encoded_len > ED25519_SIG_LEN);
226 const size_t signed_len = cert->encoded_len - ED25519_SIG_LEN;
227 checkable_out->len = signed_len;
228 memcpy(checkable_out->signature.sig,
229 cert->encoded + signed_len, ED25519_SIG_LEN);
231 if (expiration_out) {
232 *expiration_out = MIN(*expiration_out, cert->valid_until);
235 return 0;
238 /** Validates the signature on <b>cert</b> with <b>pubkey</b> relative to the
239 * current time <b>now</b>. (If <b>now</b> is 0, do not check the expiration
240 * time.) Return 0 on success, -1 on failure. Sets flags in <b>cert</b> as
241 * appropriate.
244 tor_cert_checksig(tor_cert_t *cert,
245 const ed25519_public_key_t *pubkey, time_t now)
247 ed25519_checkable_t checkable;
248 int okay;
249 time_t expires = TIME_MAX;
251 if (tor_cert_get_checkable_sig(&checkable, cert, pubkey, &expires) < 0)
252 return -1;
254 if (now && now > expires) {
255 cert->cert_expired = 1;
256 return -1;
259 if (ed25519_checksig_batch(&okay, &checkable, 1) < 0) {
260 cert->sig_bad = 1;
261 return -1;
262 } else {
263 cert->sig_ok = 1;
264 /* Only copy the checkable public key when it is different from the signing
265 * key of the certificate to avoid undefined behavior. */
266 if (cert->signing_key.pubkey != checkable.pubkey->pubkey) {
267 memcpy(cert->signing_key.pubkey, checkable.pubkey->pubkey, 32);
269 cert->cert_valid = 1;
270 return 0;
274 /** Return a string describing the status of the signature on <b>cert</b>
276 * Will always be "unchecked" unless tor_cert_checksig has been called.
278 const char *
279 tor_cert_describe_signature_status(const tor_cert_t *cert)
281 if (cert->cert_expired) {
282 return "expired";
283 } else if (cert->sig_bad) {
284 return "mis-signed";
285 } else if (cert->sig_ok) {
286 return "okay";
287 } else {
288 return "unchecked";
292 /** Return a new copy of <b>cert</b> */
293 MOCK_IMPL(tor_cert_t *,
294 tor_cert_dup,(const tor_cert_t *cert))
296 tor_cert_t *newcert = tor_memdup(cert, sizeof(tor_cert_t));
297 if (cert->encoded)
298 newcert->encoded = tor_memdup(cert->encoded, cert->encoded_len);
299 return newcert;
302 /** Return true iff cert1 and cert2 are the same cert. */
304 tor_cert_eq(const tor_cert_t *cert1, const tor_cert_t *cert2)
306 tor_assert(cert1);
307 tor_assert(cert2);
308 return cert1->encoded_len == cert2->encoded_len &&
309 tor_memeq(cert1->encoded, cert2->encoded, cert1->encoded_len);
312 /** Return true iff cert1 and cert2 are the same cert, or if they are both
313 * NULL. */
315 tor_cert_opt_eq(const tor_cert_t *cert1, const tor_cert_t *cert2)
317 if (cert1 == NULL && cert2 == NULL)
318 return 1;
319 if (!cert1 || !cert2)
320 return 0;
321 return tor_cert_eq(cert1, cert2);
324 #define RSA_ED_CROSSCERT_PREFIX "Tor TLS RSA/Ed25519 cross-certificate"
326 /** Create new cross-certification object to certify <b>ed_key</b> as the
327 * master ed25519 identity key for the RSA identity key <b>rsa_key</b>.
328 * Allocates and stores the encoded certificate in *<b>cert</b>, and returns
329 * the number of bytes stored. Returns negative on error.*/
330 ssize_t
331 tor_make_rsa_ed25519_crosscert(const ed25519_public_key_t *ed_key,
332 const crypto_pk_t *rsa_key,
333 time_t expires,
334 uint8_t **cert)
336 // It is later than 1985, since otherwise there would be no C89
337 // compilers. (Try to diagnose #22466.)
338 tor_assert_nonfatal(expires >= 15 * 365 * 86400);
340 uint8_t *res;
342 rsa_ed_crosscert_t *cc = rsa_ed_crosscert_new();
343 memcpy(cc->ed_key, ed_key->pubkey, ED25519_PUBKEY_LEN);
344 cc->expiration = (uint32_t) CEIL_DIV(expires, 3600);
345 cc->sig_len = crypto_pk_keysize(rsa_key);
346 rsa_ed_crosscert_setlen_sig(cc, crypto_pk_keysize(rsa_key));
348 ssize_t alloc_sz = rsa_ed_crosscert_encoded_len(cc);
349 tor_assert(alloc_sz > 0);
350 res = tor_malloc_zero(alloc_sz);
351 ssize_t sz = rsa_ed_crosscert_encode(res, alloc_sz, cc);
352 tor_assert(sz > 0 && sz <= alloc_sz);
354 crypto_digest_t *d = crypto_digest256_new(DIGEST_SHA256);
355 crypto_digest_add_bytes(d, RSA_ED_CROSSCERT_PREFIX,
356 strlen(RSA_ED_CROSSCERT_PREFIX));
358 const int signed_part_len = 32 + 4;
359 crypto_digest_add_bytes(d, (char*)res, signed_part_len);
361 uint8_t digest[DIGEST256_LEN];
362 crypto_digest_get_digest(d, (char*)digest, sizeof(digest));
363 crypto_digest_free(d);
365 int siglen = crypto_pk_private_sign(rsa_key,
366 (char*)rsa_ed_crosscert_getarray_sig(cc),
367 rsa_ed_crosscert_getlen_sig(cc),
368 (char*)digest, sizeof(digest));
369 tor_assert(siglen > 0 && siglen <= (int)crypto_pk_keysize(rsa_key));
370 tor_assert(siglen <= UINT8_MAX);
371 cc->sig_len = siglen;
372 rsa_ed_crosscert_setlen_sig(cc, siglen);
374 sz = rsa_ed_crosscert_encode(res, alloc_sz, cc);
375 rsa_ed_crosscert_free(cc);
376 *cert = res;
377 return sz;
381 * Check whether the <b>crosscert_len</b> byte certificate in <b>crosscert</b>
382 * is in fact a correct cross-certification of <b>master_key</b> using
383 * the RSA key <b>rsa_id_key</b>.
385 * Also reject the certificate if it expired before
386 * <b>reject_if_expired_before</b>.
388 * Return 0 on success, negative on failure.
390 MOCK_IMPL(int,
391 rsa_ed25519_crosscert_check, (const uint8_t *crosscert,
392 const size_t crosscert_len,
393 const crypto_pk_t *rsa_id_key,
394 const ed25519_public_key_t *master_key,
395 const time_t reject_if_expired_before))
397 rsa_ed_crosscert_t *cc = NULL;
398 int rv;
400 #define ERR(code, s) \
401 do { \
402 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
403 "Received a bad RSA->Ed25519 crosscert: %s", \
404 (s)); \
405 rv = (code); \
406 goto err; \
407 } while (0)
409 if (BUG(crypto_pk_keysize(rsa_id_key) > PK_BYTES))
410 return -1;
412 if (BUG(!crosscert))
413 return -1;
415 ssize_t parsed_len = rsa_ed_crosscert_parse(&cc, crosscert, crosscert_len);
416 if (parsed_len < 0 || crosscert_len != (size_t)parsed_len) {
417 ERR(-2, "Unparseable or overlong crosscert");
420 if (tor_memneq(rsa_ed_crosscert_getarray_ed_key(cc),
421 master_key->pubkey,
422 ED25519_PUBKEY_LEN)) {
423 ERR(-3, "Crosscert did not match Ed25519 key");
426 const uint32_t expiration_date = rsa_ed_crosscert_get_expiration(cc);
427 const uint64_t expiration_time = ((uint64_t)expiration_date) * 3600;
429 if (reject_if_expired_before < 0 ||
430 expiration_time < (uint64_t)reject_if_expired_before) {
431 ERR(-4, "Crosscert is expired");
434 const uint8_t *eos = rsa_ed_crosscert_get_end_of_signed(cc);
435 const uint8_t *sig = rsa_ed_crosscert_getarray_sig(cc);
436 const uint8_t siglen = rsa_ed_crosscert_get_sig_len(cc);
437 tor_assert(eos >= crosscert);
438 tor_assert((size_t)(eos - crosscert) <= crosscert_len);
439 tor_assert(siglen == rsa_ed_crosscert_getlen_sig(cc));
441 /* Compute the digest */
442 uint8_t digest[DIGEST256_LEN];
443 crypto_digest_t *d = crypto_digest256_new(DIGEST_SHA256);
444 crypto_digest_add_bytes(d, RSA_ED_CROSSCERT_PREFIX,
445 strlen(RSA_ED_CROSSCERT_PREFIX));
446 crypto_digest_add_bytes(d, (char*)crosscert, eos-crosscert);
447 crypto_digest_get_digest(d, (char*)digest, sizeof(digest));
448 crypto_digest_free(d);
450 /* Now check the signature */
451 uint8_t signed_[PK_BYTES];
452 int signed_len = crypto_pk_public_checksig(rsa_id_key,
453 (char*)signed_, sizeof(signed_),
454 (char*)sig, siglen);
455 if (signed_len < DIGEST256_LEN) {
456 ERR(-5, "Bad signature, or length of signed data not as expected");
459 if (tor_memneq(digest, signed_, DIGEST256_LEN)) {
460 ERR(-6, "The signature was good, but it didn't match the data");
463 rv = 0;
464 err:
465 rsa_ed_crosscert_free(cc);
466 return rv;
469 /** Construct and return a new empty or_handshake_certs object */
470 or_handshake_certs_t *
471 or_handshake_certs_new(void)
473 return tor_malloc_zero(sizeof(or_handshake_certs_t));
476 /** Release all storage held in <b>certs</b> */
477 void
478 or_handshake_certs_free_(or_handshake_certs_t *certs)
480 if (!certs)
481 return;
483 tor_x509_cert_free(certs->auth_cert);
484 tor_x509_cert_free(certs->link_cert);
485 tor_x509_cert_free(certs->id_cert);
487 tor_cert_free(certs->ed_id_sign);
488 tor_cert_free(certs->ed_sign_link);
489 tor_cert_free(certs->ed_sign_auth);
490 tor_free(certs->ed_rsa_crosscert);
492 memwipe(certs, 0xBD, sizeof(*certs));
493 tor_free(certs);
496 #undef ERR
497 #define ERR(s) \
498 do { \
499 log_fn(severity, LD_PROTOCOL, \
500 "Received a bad CERTS cell: %s", \
501 (s)); \
502 return 0; \
503 } while (0)
506 or_handshake_certs_rsa_ok(int severity,
507 or_handshake_certs_t *certs,
508 tor_tls_t *tls,
509 time_t now)
511 tor_x509_cert_t *link_cert = certs->link_cert;
512 tor_x509_cert_t *auth_cert = certs->auth_cert;
513 tor_x509_cert_t *id_cert = certs->id_cert;
515 if (certs->started_here) {
516 if (! (id_cert && link_cert))
517 ERR("The certs we wanted (ID, Link) were missing");
518 if (! tor_tls_cert_matches_key(tls, link_cert))
519 ERR("The link certificate didn't match the TLS public key");
520 if (! tor_tls_cert_is_valid(severity, link_cert, id_cert, now, 0))
521 ERR("The link certificate was not valid");
522 if (! tor_tls_cert_is_valid(severity, id_cert, id_cert, now, 1))
523 ERR("The ID certificate was not valid");
524 } else {
525 if (! (id_cert && auth_cert))
526 ERR("The certs we wanted (ID, Auth) were missing");
527 if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, auth_cert, id_cert, now, 1))
528 ERR("The authentication certificate was not valid");
529 if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, id_cert, id_cert, now, 1))
530 ERR("The ID certificate was not valid");
533 return 1;
536 /** Check all the ed25519 certificates in <b>certs</b> against each other, and
537 * against the peer certificate in <b>tls</b> if appropriate. On success,
538 * return 0; on failure, return a negative value and warn at level
539 * <b>severity</b> */
541 or_handshake_certs_ed25519_ok(int severity,
542 or_handshake_certs_t *certs,
543 tor_tls_t *tls,
544 time_t now)
546 ed25519_checkable_t check[10];
547 unsigned n_checkable = 0;
548 time_t expiration = TIME_MAX;
550 #define ADDCERT(cert, pk) \
551 do { \
552 tor_assert(n_checkable < ARRAY_LENGTH(check)); \
553 if (tor_cert_get_checkable_sig(&check[n_checkable++], cert, pk, \
554 &expiration) < 0) \
555 ERR("Could not get checkable cert."); \
556 } while (0)
558 if (! certs->ed_id_sign || !certs->ed_id_sign->signing_key_included) {
559 ERR("No Ed25519 signing key");
561 ADDCERT(certs->ed_id_sign, NULL);
563 if (certs->started_here) {
564 if (! certs->ed_sign_link)
565 ERR("No Ed25519 link key");
567 /* check for a match with the TLS cert. */
568 tor_x509_cert_t *peer_cert = tor_tls_get_peer_cert(tls);
569 if (BUG(!peer_cert)) {
570 /* This is a bug, because if we got to this point, we are a connection
571 * that was initiated here, and we completed a TLS handshake. The
572 * other side *must* have given us a certificate! */
573 ERR("No x509 peer cert"); // LCOV_EXCL_LINE
575 const common_digests_t *peer_cert_digests =
576 tor_x509_cert_get_cert_digests(peer_cert);
577 int okay = tor_memeq(peer_cert_digests->d[DIGEST_SHA256],
578 certs->ed_sign_link->signed_key.pubkey,
579 DIGEST256_LEN);
580 tor_x509_cert_free(peer_cert);
581 if (!okay)
582 ERR("Link certificate does not match TLS certificate");
585 ADDCERT(certs->ed_sign_link, &certs->ed_id_sign->signed_key);
587 } else {
588 if (! certs->ed_sign_auth)
589 ERR("No Ed25519 link authentication key");
590 ADDCERT(certs->ed_sign_auth, &certs->ed_id_sign->signed_key);
593 if (expiration < now) {
594 ERR("At least one certificate expired.");
597 /* Okay, we've gotten ready to check all the Ed25519 certificates.
598 * Now, we are going to check the RSA certificate's cross-certification
599 * with the ED certificates.
601 * FFFF In the future, we might want to make this optional.
604 tor_x509_cert_t *rsa_id_cert = certs->id_cert;
605 if (!rsa_id_cert) {
606 ERR("Missing legacy RSA ID certificate");
608 if (! tor_tls_cert_is_valid(severity, rsa_id_cert, rsa_id_cert, now, 1)) {
609 ERR("The legacy RSA ID certificate was not valid");
611 if (! certs->ed_rsa_crosscert) {
612 ERR("Missing RSA->Ed25519 crosscert");
614 crypto_pk_t *rsa_id_key = tor_tls_cert_get_key(rsa_id_cert);
615 if (!rsa_id_key) {
616 ERR("RSA ID cert had no RSA key");
619 if (rsa_ed25519_crosscert_check(certs->ed_rsa_crosscert,
620 certs->ed_rsa_crosscert_len,
621 rsa_id_key,
622 &certs->ed_id_sign->signing_key,
623 now) < 0) {
624 crypto_pk_free(rsa_id_key);
625 ERR("Invalid RSA->Ed25519 crosscert");
627 crypto_pk_free(rsa_id_key);
628 rsa_id_key = NULL;
630 /* FFFF We could save a little time in the client case by queueing
631 * this batch to check it later, along with the signature from the
632 * AUTHENTICATE cell. That will change our data flow a bit, though,
633 * so I say "postpone". */
635 if (ed25519_checksig_batch(NULL, check, n_checkable) < 0) {
636 ERR("At least one Ed25519 certificate was badly signed");
639 return 1;
642 /** Check whether an RSA-TAP cross-certification is correct. Return 0 if it
643 * is, -1 if it isn't. */
644 MOCK_IMPL(int,
645 check_tap_onion_key_crosscert,(const uint8_t *crosscert,
646 int crosscert_len,
647 const crypto_pk_t *onion_pkey,
648 const ed25519_public_key_t *master_id_pkey,
649 const uint8_t *rsa_id_digest))
651 uint8_t *cc = tor_malloc(crypto_pk_keysize(onion_pkey));
652 int cc_len =
653 crypto_pk_public_checksig(onion_pkey,
654 (char*)cc,
655 crypto_pk_keysize(onion_pkey),
656 (const char*)crosscert,
657 crosscert_len);
658 if (cc_len < 0) {
659 goto err;
661 if (cc_len < DIGEST_LEN + ED25519_PUBKEY_LEN) {
662 log_warn(LD_DIR, "Short signature on cross-certification with TAP key");
663 goto err;
665 if (tor_memneq(cc, rsa_id_digest, DIGEST_LEN) ||
666 tor_memneq(cc + DIGEST_LEN, master_id_pkey->pubkey,
667 ED25519_PUBKEY_LEN)) {
668 log_warn(LD_DIR, "Incorrect cross-certification with TAP key");
669 goto err;
672 tor_free(cc);
673 return 0;
674 err:
675 tor_free(cc);
676 return -1;
680 * Check the Ed certificates and/or the RSA certificates, as appropriate. If
681 * we obtained an Ed25519 identity, set *ed_id_out. If we obtained an RSA
682 * identity, set *rs_id_out. Otherwise, set them both to NULL.
684 void
685 or_handshake_certs_check_both(int severity,
686 or_handshake_certs_t *certs,
687 tor_tls_t *tls,
688 time_t now,
689 const ed25519_public_key_t **ed_id_out,
690 const common_digests_t **rsa_id_out)
692 tor_assert(ed_id_out);
693 tor_assert(rsa_id_out);
695 *ed_id_out = NULL;
696 *rsa_id_out = NULL;
698 if (certs->ed_id_sign) {
699 if (or_handshake_certs_ed25519_ok(severity, certs, tls, now)) {
700 tor_assert(certs->ed_id_sign);
701 tor_assert(certs->id_cert);
703 *ed_id_out = &certs->ed_id_sign->signing_key;
704 *rsa_id_out = tor_x509_cert_get_id_digests(certs->id_cert);
706 /* If we reached this point, we did not look at any of the
707 * subsidiary RSA certificates, so we'd better just remove them.
709 tor_x509_cert_free(certs->link_cert);
710 tor_x509_cert_free(certs->auth_cert);
711 certs->link_cert = certs->auth_cert = NULL;
713 /* We do _not_ fall through here. If you provided us Ed25519
714 * certificates, we expect to verify them! */
715 } else {
716 /* No ed25519 keys given in the CERTS cell */
717 if (or_handshake_certs_rsa_ok(severity, certs, tls, now)) {
718 *rsa_id_out = tor_x509_cert_get_id_digests(certs->id_cert);
723 /* === ENCODING === */
725 /* Encode the ed25519 certificate <b>cert</b> and put the newly allocated
726 * string in <b>cert_str_out</b>. Return 0 on success else a negative value. */
728 tor_cert_encode_ed22519(const tor_cert_t *cert, char **cert_str_out)
730 int ret = -1;
731 char *ed_cert_b64 = NULL;
732 size_t ed_cert_b64_len;
734 tor_assert(cert);
735 tor_assert(cert_str_out);
737 /* Get the encoded size and add the NUL byte. */
738 ed_cert_b64_len = base64_encode_size(cert->encoded_len,
739 BASE64_ENCODE_MULTILINE) + 1;
740 ed_cert_b64 = tor_malloc_zero(ed_cert_b64_len);
742 /* Base64 encode the encoded certificate. */
743 if (base64_encode(ed_cert_b64, ed_cert_b64_len,
744 (const char *) cert->encoded, cert->encoded_len,
745 BASE64_ENCODE_MULTILINE) < 0) {
746 /* LCOV_EXCL_START */
747 log_err(LD_BUG, "Couldn't base64-encode ed22519 cert!");
748 goto err;
749 /* LCOV_EXCL_STOP */
752 /* Put everything together in a NUL terminated string. */
753 tor_asprintf(cert_str_out,
754 "-----BEGIN ED25519 CERT-----\n"
755 "%s"
756 "-----END ED25519 CERT-----",
757 ed_cert_b64);
758 /* Success! */
759 ret = 0;
761 err:
762 tor_free(ed_cert_b64);
763 return ret;