1 /* Copyright (c) 2017, Google Inc. 2 * 3 * Permission to use, copy, modify, and/or distribute this software for any 4 * purpose with or without fee is hereby granted, provided that the above 5 * copyright notice and this permission notice appear in all copies. 6 * 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 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 26 static void ed25519_free(EVP_PKEY *pkey) { 27 if (pkey->pkey.ptr != NULL) { 28 ED25519_KEY *key = pkey->pkey.ptr; 29 OPENSSL_cleanse(key, sizeof(ED25519_KEY)); 30 OPENSSL_free(key); 31 pkey->pkey.ptr = NULL; 32 } 33 } 34 35 static int set_pubkey(EVP_PKEY *pkey, const uint8_t pubkey[32]) { 36 ED25519_KEY *key = OPENSSL_malloc(sizeof(ED25519_KEY)); 37 if (key == NULL) { 38 OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE); 39 return 0; 40 } 41 key->has_private = 0; 42 OPENSSL_memcpy(key->key.pub.value, pubkey, 32); 43 44 ed25519_free(pkey); 45 pkey->pkey.ptr = key; 46 return 1; 47 } 48 49 static int set_privkey(EVP_PKEY *pkey, const uint8_t privkey[64]) { 50 ED25519_KEY *key = OPENSSL_malloc(sizeof(ED25519_KEY)); 51 if (key == NULL) { 52 OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE); 53 return 0; 54 } 55 key->has_private = 1; 56 OPENSSL_memcpy(key->key.priv, privkey, 64); 57 58 ed25519_free(pkey); 59 pkey->pkey.ptr = key; 60 return 1; 61 } 62 63 static int ed25519_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { 64 /* See draft-ietf-curdle-pkix-04, section 4. */ 65 66 /* The parameters must be omitted. Public keys have length 32. */ 67 if (CBS_len(params) != 0 || 68 CBS_len(key) != 32) { 69 OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); 70 return 0; 71 } 72 73 return set_pubkey(out, CBS_data(key)); 74 } 75 76 static int ed25519_pub_encode(CBB *out, const EVP_PKEY *pkey) { 77 const ED25519_KEY *key = pkey->pkey.ptr; 78 79 /* See draft-ietf-curdle-pkix-04, section 4. */ 80 CBB spki, algorithm, oid, key_bitstring; 81 if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || 82 !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || 83 !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || 84 !CBB_add_bytes(&oid, ed25519_asn1_meth.oid, ed25519_asn1_meth.oid_len) || 85 !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || 86 !CBB_add_u8(&key_bitstring, 0 /* padding */) || 87 !CBB_add_bytes(&key_bitstring, key->key.pub.value, 32) || 88 !CBB_flush(out)) { 89 OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); 90 return 0; 91 } 92 93 return 1; 94 } 95 96 static int ed25519_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { 97 const ED25519_KEY *a_key = a->pkey.ptr; 98 const ED25519_KEY *b_key = b->pkey.ptr; 99 return OPENSSL_memcmp(a_key->key.pub.value, b_key->key.pub.value, 32) == 0; 100 } 101 102 static int ed25519_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) { 103 /* See draft-ietf-curdle-pkix-04, section 7. */ 104 105 /* Parameters must be empty. The key is a 32-byte value wrapped in an extra 106 * OCTET STRING layer. */ 107 CBS inner; 108 if (CBS_len(params) != 0 || 109 !CBS_get_asn1(key, &inner, CBS_ASN1_OCTETSTRING) || 110 CBS_len(key) != 0 || 111 CBS_len(&inner) != 32) { 112 OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); 113 return 0; 114 } 115 116 /* The PKCS#8 encoding stores only the 32-byte seed, so we must recover the 117 * full representation which we use from it. */ 118 uint8_t pubkey[32], privkey[64]; 119 ED25519_keypair_from_seed(pubkey, privkey, CBS_data(&inner)); 120 return set_privkey(out, privkey); 121 } 122 123 static int ed25519_priv_encode(CBB *out, const EVP_PKEY *pkey) { 124 ED25519_KEY *key = pkey->pkey.ptr; 125 if (!key->has_private) { 126 OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY); 127 return 0; 128 } 129 130 /* See draft-ietf-curdle-pkix-04, section 7. */ 131 CBB pkcs8, algorithm, oid, private_key, inner; 132 if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) || 133 !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) || 134 !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) || 135 !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) || 136 !CBB_add_bytes(&oid, ed25519_asn1_meth.oid, ed25519_asn1_meth.oid_len) || 137 !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) || 138 !CBB_add_asn1(&private_key, &inner, CBS_ASN1_OCTETSTRING) || 139 /* The PKCS#8 encoding stores only the 32-byte seed which is the first 32 140 * bytes of the private key. */ 141 !CBB_add_bytes(&inner, key->key.priv, 32) || 142 !CBB_flush(out)) { 143 OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); 144 return 0; 145 } 146 147 return 1; 148 } 149 150 static int ed25519_size(const EVP_PKEY *pkey) { return 64; } 151 152 static int ed25519_bits(const EVP_PKEY *pkey) { return 256; } 153 154 const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = { 155 EVP_PKEY_ED25519, 156 {0x2b, 0x65, 0x70}, 157 3, 158 ed25519_pub_decode, 159 ed25519_pub_encode, 160 ed25519_pub_cmp, 161 ed25519_priv_decode, 162 ed25519_priv_encode, 163 NULL /* pkey_opaque */, 164 ed25519_size, 165 ed25519_bits, 166 NULL /* param_missing */, 167 NULL /* param_copy */, 168 NULL /* param_cmp */, 169 ed25519_free, 170 }; 171 172 EVP_PKEY *EVP_PKEY_new_ed25519_public(const uint8_t public_key[32]) { 173 EVP_PKEY *ret = EVP_PKEY_new(); 174 if (ret == NULL || 175 !EVP_PKEY_set_type(ret, EVP_PKEY_ED25519) || 176 !set_pubkey(ret, public_key)) { 177 EVP_PKEY_free(ret); 178 return NULL; 179 } 180 181 return ret; 182 } 183 184 EVP_PKEY *EVP_PKEY_new_ed25519_private(const uint8_t private_key[64]) { 185 EVP_PKEY *ret = EVP_PKEY_new(); 186 if (ret == NULL || 187 !EVP_PKEY_set_type(ret, EVP_PKEY_ED25519) || 188 !set_privkey(ret, private_key)) { 189 EVP_PKEY_free(ret); 190 return NULL; 191 } 192 193 return ret; 194 } 195