1 // Copyright 2017 The BoringSSL Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <openssl/evp.h>
16
17 #include <openssl/bytestring.h>
18 #include <openssl/curve25519.h>
19 #include <openssl/err.h>
20 #include <openssl/mem.h>
21
22 #include "../internal.h"
23 #include "internal.h"
24
25
ed25519_free(EVP_PKEY * pkey)26 static void ed25519_free(EVP_PKEY *pkey) {
27 OPENSSL_free(pkey->pkey);
28 pkey->pkey = NULL;
29 }
30
ed25519_set_priv_raw(EVP_PKEY * pkey,const uint8_t * in,size_t len)31 static int ed25519_set_priv_raw(EVP_PKEY *pkey, const uint8_t *in, size_t len) {
32 if (len != 32) {
33 OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
34 return 0;
35 }
36
37 ED25519_KEY *key =
38 reinterpret_cast<ED25519_KEY *>(OPENSSL_malloc(sizeof(ED25519_KEY)));
39 if (key == NULL) {
40 return 0;
41 }
42
43 // The RFC 8032 encoding stores only the 32-byte seed, so we must recover the
44 // full representation which we use from it.
45 uint8_t pubkey_unused[32];
46 ED25519_keypair_from_seed(pubkey_unused, key->key, in);
47 key->has_private = 1;
48
49 ed25519_free(pkey);
50 pkey->pkey = key;
51 return 1;
52 }
53
ed25519_set_pub_raw(EVP_PKEY * pkey,const uint8_t * in,size_t len)54 static int ed25519_set_pub_raw(EVP_PKEY *pkey, const uint8_t *in, size_t len) {
55 if (len != 32) {
56 OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
57 return 0;
58 }
59
60 ED25519_KEY *key =
61 reinterpret_cast<ED25519_KEY *>(OPENSSL_malloc(sizeof(ED25519_KEY)));
62 if (key == NULL) {
63 return 0;
64 }
65
66 OPENSSL_memcpy(key->key + ED25519_PUBLIC_KEY_OFFSET, in, 32);
67 key->has_private = 0;
68
69 ed25519_free(pkey);
70 pkey->pkey = key;
71 return 1;
72 }
73
ed25519_get_priv_raw(const EVP_PKEY * pkey,uint8_t * out,size_t * out_len)74 static int ed25519_get_priv_raw(const EVP_PKEY *pkey, uint8_t *out,
75 size_t *out_len) {
76 const ED25519_KEY *key = reinterpret_cast<const ED25519_KEY *>(pkey->pkey);
77 if (!key->has_private) {
78 OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
79 return 0;
80 }
81
82 if (out == NULL) {
83 *out_len = 32;
84 return 1;
85 }
86
87 if (*out_len < 32) {
88 OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
89 return 0;
90 }
91
92 // The raw private key format is the first 32 bytes of the private key.
93 OPENSSL_memcpy(out, key->key, 32);
94 *out_len = 32;
95 return 1;
96 }
97
ed25519_get_pub_raw(const EVP_PKEY * pkey,uint8_t * out,size_t * out_len)98 static int ed25519_get_pub_raw(const EVP_PKEY *pkey, uint8_t *out,
99 size_t *out_len) {
100 const ED25519_KEY *key = reinterpret_cast<const ED25519_KEY *>(pkey->pkey);
101 if (out == NULL) {
102 *out_len = 32;
103 return 1;
104 }
105
106 if (*out_len < 32) {
107 OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
108 return 0;
109 }
110
111 OPENSSL_memcpy(out, key->key + ED25519_PUBLIC_KEY_OFFSET, 32);
112 *out_len = 32;
113 return 1;
114 }
115
ed25519_pub_decode(EVP_PKEY * out,CBS * params,CBS * key)116 static int ed25519_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
117 // See RFC 8410, section 4.
118
119 // The parameters must be omitted. Public keys have length 32.
120 if (CBS_len(params) != 0) {
121 OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
122 return 0;
123 }
124
125 return ed25519_set_pub_raw(out, CBS_data(key), CBS_len(key));
126 }
127
ed25519_pub_encode(CBB * out,const EVP_PKEY * pkey)128 static int ed25519_pub_encode(CBB *out, const EVP_PKEY *pkey) {
129 const ED25519_KEY *key = reinterpret_cast<const ED25519_KEY *>(pkey->pkey);
130
131 // See RFC 8410, section 4.
132 CBB spki, algorithm, key_bitstring;
133 if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
134 !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
135 !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, ed25519_asn1_meth.oid,
136 ed25519_asn1_meth.oid_len) ||
137 !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
138 !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
139 !CBB_add_bytes(&key_bitstring, key->key + ED25519_PUBLIC_KEY_OFFSET,
140 32) ||
141 !CBB_flush(out)) {
142 OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
143 return 0;
144 }
145
146 return 1;
147 }
148
ed25519_pub_cmp(const EVP_PKEY * a,const EVP_PKEY * b)149 static int ed25519_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
150 const ED25519_KEY *a_key = reinterpret_cast<const ED25519_KEY *>(a->pkey);
151 const ED25519_KEY *b_key = reinterpret_cast<const ED25519_KEY *>(b->pkey);
152 return OPENSSL_memcmp(a_key->key + ED25519_PUBLIC_KEY_OFFSET,
153 b_key->key + ED25519_PUBLIC_KEY_OFFSET, 32) == 0;
154 }
155
ed25519_priv_decode(EVP_PKEY * out,CBS * params,CBS * key)156 static int ed25519_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
157 // See RFC 8410, section 7.
158
159 // Parameters must be empty. The key is a 32-byte value wrapped in an extra
160 // OCTET STRING layer.
161 CBS inner;
162 if (CBS_len(params) != 0 ||
163 !CBS_get_asn1(key, &inner, CBS_ASN1_OCTETSTRING) || CBS_len(key) != 0) {
164 OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
165 return 0;
166 }
167
168 return ed25519_set_priv_raw(out, CBS_data(&inner), CBS_len(&inner));
169 }
170
ed25519_priv_encode(CBB * out,const EVP_PKEY * pkey)171 static int ed25519_priv_encode(CBB *out, const EVP_PKEY *pkey) {
172 const ED25519_KEY *key = reinterpret_cast<const ED25519_KEY *>(pkey->pkey);
173 if (!key->has_private) {
174 OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY);
175 return 0;
176 }
177
178 // See RFC 8410, section 7.
179 CBB pkcs8, algorithm, private_key, inner;
180 if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
181 !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
182 !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
183 !CBB_add_asn1_element(&algorithm, CBS_ASN1_OBJECT, ed25519_asn1_meth.oid,
184 ed25519_asn1_meth.oid_len) ||
185 !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
186 !CBB_add_asn1(&private_key, &inner, CBS_ASN1_OCTETSTRING) ||
187 // The PKCS#8 encoding stores only the 32-byte seed which is the first 32
188 // bytes of the private key.
189 !CBB_add_bytes(&inner, key->key, 32) || //
190 !CBB_flush(out)) {
191 OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
192 return 0;
193 }
194
195 return 1;
196 }
197
ed25519_size(const EVP_PKEY * pkey)198 static int ed25519_size(const EVP_PKEY *pkey) { return 64; }
199
ed25519_bits(const EVP_PKEY * pkey)200 static int ed25519_bits(const EVP_PKEY *pkey) { return 253; }
201
202 const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
203 EVP_PKEY_ED25519,
204 {0x2b, 0x65, 0x70},
205 3,
206 &ed25519_pkey_meth,
207 ed25519_pub_decode,
208 ed25519_pub_encode,
209 ed25519_pub_cmp,
210 ed25519_priv_decode,
211 ed25519_priv_encode,
212 ed25519_set_priv_raw,
213 ed25519_set_pub_raw,
214 ed25519_get_priv_raw,
215 ed25519_get_pub_raw,
216 /*set1_tls_encodedpoint=*/NULL,
217 /*get1_tls_encodedpoint=*/NULL,
218 /*pkey_opaque=*/NULL,
219 ed25519_size,
220 ed25519_bits,
221 /*param_missing=*/NULL,
222 /*param_copy=*/NULL,
223 /*param_cmp=*/NULL,
224 ed25519_free,
225 };
226