1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
7 * \brief Implementation for ed25519-signed certificates as used in the Tor
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.
44 tor_cert_create_raw(const ed25519_keypair_t
*signing_key
,
46 uint8_t signed_key_type
,
47 const uint8_t signed_key_info
[32],
48 time_t now
, time_t lifetime
,
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
);
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
);
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) {
83 log_warn(LD_BUG
, "Can't sign certificate");
87 memcpy(sig
, signature
.sig
, ED25519_SIG_LEN
);
89 torcert
= tor_cert_parse(encoded
, real_len
);
92 log_warn(LD_BUG
, "Generated a certificate we cannot parse");
97 if (tor_cert_checksig(torcert
, &signing_key
->pubkey
, now
) < 0) {
99 log_warn(LD_BUG
, "Generated a certificate whose signature we can't "
100 "check: %s", tor_cert_describe_signature_status(torcert
));
109 /* LCOV_EXCL_START */
111 tor_cert_free(torcert
);
116 ed25519_cert_free(cert
);
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
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.
131 tor_cert_create_ed25519(const ed25519_keypair_t
*signing_key
,
133 const ed25519_public_key_t
*signed_key
,
134 time_t now
, time_t lifetime
,
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>. */
144 tor_cert_free_(tor_cert_t
*cert
)
150 memwipe(cert
->encoded
, 0, cert
->encoded_len
);
151 tor_free(cert
->encoded
);
153 memwipe(cert
, 0, sizeof(tor_cert_t
));
157 /** Parse a certificate encoded with <b>len</b> bytes in <b>encoded</b>. */
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
)
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;
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
)
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 */
199 ed25519_cert_free(parsed
);
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
)
217 if (cert
->signing_key_included
)
218 pubkey
= &cert
->signing_key
;
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
);
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
244 tor_cert_checksig(tor_cert_t
*cert
,
245 const ed25519_public_key_t
*pubkey
, time_t now
)
247 ed25519_checkable_t checkable
;
249 time_t expires
= TIME_MAX
;
251 if (tor_cert_get_checkable_sig(&checkable
, cert
, pubkey
, &expires
) < 0)
254 if (now
&& now
> expires
) {
255 cert
->cert_expired
= 1;
259 if (ed25519_checksig_batch(&okay
, &checkable
, 1) < 0) {
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;
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.
279 tor_cert_describe_signature_status(const tor_cert_t
*cert
)
281 if (cert
->cert_expired
) {
283 } else if (cert
->sig_bad
) {
285 } else if (cert
->sig_ok
) {
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
));
298 newcert
->encoded
= tor_memdup(cert
->encoded
, cert
->encoded_len
);
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
)
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
315 tor_cert_opt_eq(const tor_cert_t
*cert1
, const tor_cert_t
*cert2
)
317 if (cert1
== NULL
&& cert2
== NULL
)
319 if (!cert1
|| !cert2
)
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.*/
331 tor_make_rsa_ed25519_crosscert(const ed25519_public_key_t
*ed_key
,
332 const crypto_pk_t
*rsa_key
,
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);
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
);
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.
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
;
400 #define ERR(code, s) \
402 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \
403 "Received a bad RSA->Ed25519 crosscert: %s", \
409 if (BUG(crypto_pk_keysize(rsa_id_key
) > PK_BYTES
))
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
),
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_
),
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");
465 rsa_ed_crosscert_free(cc
);
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> */
478 or_handshake_certs_free_(or_handshake_certs_t
*certs
)
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
));
499 log_fn(severity, LD_PROTOCOL, \
500 "Received a bad CERTS cell: %s", \
506 or_handshake_certs_rsa_ok(int severity
,
507 or_handshake_certs_t
*certs
,
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");
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");
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
541 or_handshake_certs_ed25519_ok(int severity
,
542 or_handshake_certs_t
*certs
,
546 ed25519_checkable_t check
[10];
547 unsigned n_checkable
= 0;
548 time_t expiration
= TIME_MAX
;
550 #define ADDCERT(cert, pk) \
552 tor_assert(n_checkable < ARRAY_LENGTH(check)); \
553 if (tor_cert_get_checkable_sig(&check[n_checkable++], cert, pk, \
555 ERR("Could not get checkable cert."); \
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
,
580 tor_x509_cert_free(peer_cert
);
582 ERR("Link certificate does not match TLS certificate");
585 ADDCERT(certs
->ed_sign_link
, &certs
->ed_id_sign
->signed_key
);
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
;
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
);
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
,
622 &certs
->ed_id_sign
->signing_key
,
624 crypto_pk_free(rsa_id_key
);
625 ERR("Invalid RSA->Ed25519 crosscert");
627 crypto_pk_free(rsa_id_key
);
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");
642 /** Check whether an RSA-TAP cross-certification is correct. Return 0 if it
643 * is, -1 if it isn't. */
645 check_tap_onion_key_crosscert
,(const uint8_t *crosscert
,
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
));
653 crypto_pk_public_checksig(onion_pkey
,
655 crypto_pk_keysize(onion_pkey
),
656 (const char*)crosscert
,
661 if (cc_len
< DIGEST_LEN
+ ED25519_PUBKEY_LEN
) {
662 log_warn(LD_DIR
, "Short signature on cross-certification with TAP key");
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");
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.
685 or_handshake_certs_check_both(int severity
,
686 or_handshake_certs_t
*certs
,
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
);
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! */
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
)
731 char *ed_cert_b64
= NULL
;
732 size_t ed_cert_b64_len
;
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!");
752 /* Put everything together in a NUL terminated string. */
753 tor_asprintf(cert_str_out
,
754 "-----BEGIN ED25519 CERT-----\n"
756 "-----END ED25519 CERT-----",
762 tor_free(ed_cert_b64
);