1 /* Copyright (c) 2014-2016, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
7 * \brief Implementation for ed25519-signed certificates as used in the Tor
13 #include "ed25519_cert.h"
17 #include "link_handshake.h"
19 /** Helper for tor_cert_create(): signs any 32 bytes, not just an ed25519
23 tor_cert_sign_impl(const ed25519_keypair_t
*signing_key
,
25 uint8_t signed_key_type
,
26 const uint8_t signed_key_info
[32],
27 time_t now
, time_t lifetime
,
30 tor_cert_t
*torcert
= NULL
;
32 ed25519_cert_t
*cert
= ed25519_cert_new();
33 cert
->cert_type
= cert_type
;
34 cert
->exp_field
= (uint32_t) CEIL_DIV(now
+ lifetime
, 3600);
35 cert
->cert_key_type
= signed_key_type
;
36 memcpy(cert
->certified_key
, signed_key_info
, 32);
38 if (flags
& CERT_FLAG_INCLUDE_SIGNING_KEY
) {
39 ed25519_cert_extension_t
*ext
= ed25519_cert_extension_new();
40 ext
->ext_type
= CERTEXT_SIGNED_WITH_KEY
;
41 memcpy(ext
->un_signing_key
, signing_key
->pubkey
.pubkey
, 32);
42 ed25519_cert_add_ext(cert
, ext
);
46 const ssize_t alloc_len
= ed25519_cert_encoded_len(cert
);
47 tor_assert(alloc_len
> 0);
48 uint8_t *encoded
= tor_malloc(alloc_len
);
49 const ssize_t real_len
= ed25519_cert_encode(encoded
, alloc_len
, cert
);
52 tor_assert(real_len
== alloc_len
);
53 tor_assert(real_len
> ED25519_SIG_LEN
);
54 uint8_t *sig
= encoded
+ (real_len
- ED25519_SIG_LEN
);
55 tor_assert(tor_mem_is_zero((char*)sig
, ED25519_SIG_LEN
));
57 ed25519_signature_t signature
;
58 if (ed25519_sign(&signature
, encoded
,
59 real_len
-ED25519_SIG_LEN
, signing_key
)<0) {
60 log_warn(LD_BUG
, "Can't sign certificate");
63 memcpy(sig
, signature
.sig
, ED25519_SIG_LEN
);
65 torcert
= tor_cert_parse(encoded
, real_len
);
67 log_warn(LD_BUG
, "Generated a certificate we cannot parse");
71 if (tor_cert_checksig(torcert
, &signing_key
->pubkey
, now
) < 0) {
72 log_warn(LD_BUG
, "Generated a certificate whose signature we can't check");
81 tor_cert_free(torcert
);
84 ed25519_cert_free(cert
);
90 * Create and return a new new certificate of type <b>cert_type</b> to
91 * authenticate <b>signed_key</b> using the key <b>signing_key</b>. The
92 * certificate should remain valid for at least <b>lifetime</b> seconds after
95 * If CERT_FLAG_INCLUDE_SIGNING_KEY is set in <b>flags</b>, embed
96 * the public part of <b>signing_key</b> in the certificate.
99 tor_cert_create(const ed25519_keypair_t
*signing_key
,
101 const ed25519_public_key_t
*signed_key
,
102 time_t now
, time_t lifetime
,
105 return tor_cert_sign_impl(signing_key
, cert_type
,
106 SIGNED_KEY_TYPE_ED25519
, signed_key
->pubkey
,
107 now
, lifetime
, flags
);
110 /** Release all storage held for <b>cert</b>. */
112 tor_cert_free(tor_cert_t
*cert
)
118 memwipe(cert
->encoded
, 0, cert
->encoded_len
);
119 tor_free(cert
->encoded
);
121 memwipe(cert
, 0, sizeof(tor_cert_t
));
125 /** Parse a certificate encoded with <b>len</b> bytes in <b>encoded</b>. */
127 tor_cert_parse(const uint8_t *encoded
, const size_t len
)
129 tor_cert_t
*cert
= NULL
;
130 ed25519_cert_t
*parsed
= NULL
;
131 ssize_t got_len
= ed25519_cert_parse(&parsed
, encoded
, len
);
132 if (got_len
< 0 || (size_t) got_len
!= len
)
135 cert
= tor_malloc_zero(sizeof(tor_cert_t
));
136 cert
->encoded
= tor_memdup(encoded
, len
);
137 cert
->encoded_len
= len
;
139 memcpy(cert
->signed_key
.pubkey
, parsed
->certified_key
, 32);
140 cert
->valid_until
= parsed
->exp_field
* 3600;
141 cert
->cert_type
= parsed
->cert_type
;
143 for (unsigned i
= 0; i
< ed25519_cert_getlen_ext(parsed
); ++i
) {
144 ed25519_cert_extension_t
*ext
= ed25519_cert_get_ext(parsed
, i
);
145 if (ext
->ext_type
== CERTEXT_SIGNED_WITH_KEY
) {
146 if (cert
->signing_key_included
)
149 cert
->signing_key_included
= 1;
150 memcpy(cert
->signing_key
.pubkey
, ext
->un_signing_key
, 32);
151 } else if (ext
->ext_flags
& CERTEXT_FLAG_AFFECTS_VALIDATION
) {
152 /* Unrecognized extension with affects_validation set */
162 ed25519_cert_free(parsed
);
166 /** Fill in <b>checkable_out</b> with the information needed to check
167 * the signature on <b>cert</b> with <b>pubkey</b>. */
169 tor_cert_get_checkable_sig(ed25519_checkable_t
*checkable_out
,
170 const tor_cert_t
*cert
,
171 const ed25519_public_key_t
*pubkey
)
174 if (cert
->signing_key_included
)
175 pubkey
= &cert
->signing_key
;
180 checkable_out
->msg
= cert
->encoded
;
181 checkable_out
->pubkey
= pubkey
;
182 tor_assert(cert
->encoded_len
> ED25519_SIG_LEN
);
183 const size_t signed_len
= cert
->encoded_len
- ED25519_SIG_LEN
;
184 checkable_out
->len
= signed_len
;
185 memcpy(checkable_out
->signature
.sig
,
186 cert
->encoded
+ signed_len
, ED25519_SIG_LEN
);
191 /** Validates the signature on <b>cert</b> with <b>pubkey</b> relative to the
192 * current time <b>now</b>. (If <b>now</b> is 0, do not check the expiration
193 * time.) Return 0 on success, -1 on failure. Sets flags in <b>cert</b> as
197 tor_cert_checksig(tor_cert_t
*cert
,
198 const ed25519_public_key_t
*pubkey
, time_t now
)
200 ed25519_checkable_t checkable
;
203 if (now
&& now
> cert
->valid_until
) {
204 cert
->cert_expired
= 1;
208 if (tor_cert_get_checkable_sig(&checkable
, cert
, pubkey
) < 0)
211 if (ed25519_checksig_batch(&okay
, &checkable
, 1) < 0) {
216 /* Only copy the checkable public key when it is different from the signing
217 * key of the certificate to avoid undefined behavior. */
218 if (cert
->signing_key
.pubkey
!= checkable
.pubkey
->pubkey
) {
219 memcpy(cert
->signing_key
.pubkey
, checkable
.pubkey
->pubkey
, 32);
221 cert
->cert_valid
= 1;
226 /** Return a new copy of <b>cert</b> */
228 tor_cert_dup(const tor_cert_t
*cert
)
230 tor_cert_t
*newcert
= tor_memdup(cert
, sizeof(tor_cert_t
));
232 newcert
->encoded
= tor_memdup(cert
->encoded
, cert
->encoded_len
);
236 /** Return true iff cert1 and cert2 are the same cert. */
238 tor_cert_eq(const tor_cert_t
*cert1
, const tor_cert_t
*cert2
)
242 return cert1
->encoded_len
== cert2
->encoded_len
&&
243 tor_memeq(cert1
->encoded
, cert2
->encoded
, cert1
->encoded_len
);
246 /** Return true iff cert1 and cert2 are the same cert, or if they are both
249 tor_cert_opt_eq(const tor_cert_t
*cert1
, const tor_cert_t
*cert2
)
251 if (cert1
== NULL
&& cert2
== NULL
)
253 if (!cert1
|| !cert2
)
255 return tor_cert_eq(cert1
, cert2
);
258 /** Create new cross-certification object to certify <b>ed_key</b> as the
259 * master ed25519 identity key for the RSA identity key <b>rsa_key</b>.
260 * Allocates and stores the encoded certificate in *<b>cert</b>, and returns
261 * the number of bytes stored. Returns negative on error.*/
263 tor_make_rsa_ed25519_crosscert(const ed25519_public_key_t
*ed_key
,
264 const crypto_pk_t
*rsa_key
,
270 rsa_ed_crosscert_t
*cc
= rsa_ed_crosscert_new();
271 memcpy(cc
->ed_key
, ed_key
->pubkey
, ED25519_PUBKEY_LEN
);
272 cc
->expiration
= (uint32_t) CEIL_DIV(expires
, 3600);
273 cc
->sig_len
= crypto_pk_keysize(rsa_key
);
274 rsa_ed_crosscert_setlen_sig(cc
, crypto_pk_keysize(rsa_key
));
276 ssize_t alloc_sz
= rsa_ed_crosscert_encoded_len(cc
);
277 tor_assert(alloc_sz
> 0);
278 res
= tor_malloc_zero(alloc_sz
);
279 ssize_t sz
= rsa_ed_crosscert_encode(res
, alloc_sz
, cc
);
280 tor_assert(sz
> 0 && sz
<= alloc_sz
);
282 const int signed_part_len
= 32 + 4;
283 int siglen
= crypto_pk_private_sign(rsa_key
,
284 (char*)rsa_ed_crosscert_getarray_sig(cc
),
285 rsa_ed_crosscert_getlen_sig(cc
),
286 (char*)res
, signed_part_len
);
287 tor_assert(siglen
> 0 && siglen
<= (int)crypto_pk_keysize(rsa_key
));
288 tor_assert(siglen
<= UINT8_MAX
);
289 cc
->sig_len
= siglen
;
290 rsa_ed_crosscert_setlen_sig(cc
, siglen
);
292 sz
= rsa_ed_crosscert_encode(res
, alloc_sz
, cc
);
293 rsa_ed_crosscert_free(cc
);