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/curve25519.h> |
18 | #include <openssl/err.h> |
19 | #include <openssl/mem.h> |
20 | |
21 | #include "internal.h" |
22 | |
23 | |
24 | // Ed25519 has no parameters to copy. |
25 | static int pkey_ed25519_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { return 1; } |
26 | |
27 | static int pkey_ed25519_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { |
28 | ED25519_KEY *key = OPENSSL_malloc(sizeof(ED25519_KEY)); |
29 | if (key == NULL) { |
30 | OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE); |
31 | return 0; |
32 | } |
33 | |
34 | if (!EVP_PKEY_set_type(pkey, EVP_PKEY_ED25519)) { |
35 | OPENSSL_free(key); |
36 | return 0; |
37 | } |
38 | |
39 | uint8_t pubkey_unused[32]; |
40 | ED25519_keypair(pubkey_unused, key->key.priv); |
41 | key->has_private = 1; |
42 | |
43 | OPENSSL_free(pkey->pkey.ptr); |
44 | pkey->pkey.ptr = key; |
45 | return 1; |
46 | } |
47 | |
48 | static int pkey_ed25519_sign_message(EVP_PKEY_CTX *ctx, uint8_t *sig, |
49 | size_t *siglen, const uint8_t *tbs, |
50 | size_t tbslen) { |
51 | ED25519_KEY *key = ctx->pkey->pkey.ptr; |
52 | if (!key->has_private) { |
53 | OPENSSL_PUT_ERROR(EVP, EVP_R_NOT_A_PRIVATE_KEY); |
54 | return 0; |
55 | } |
56 | |
57 | if (sig == NULL) { |
58 | *siglen = 64; |
59 | return 1; |
60 | } |
61 | |
62 | if (*siglen < 64) { |
63 | OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); |
64 | return 0; |
65 | } |
66 | |
67 | if (!ED25519_sign(sig, tbs, tbslen, key->key.priv)) { |
68 | return 0; |
69 | } |
70 | |
71 | *siglen = 64; |
72 | return 1; |
73 | } |
74 | |
75 | static int pkey_ed25519_verify_message(EVP_PKEY_CTX *ctx, const uint8_t *sig, |
76 | size_t siglen, const uint8_t *tbs, |
77 | size_t tbslen) { |
78 | ED25519_KEY *key = ctx->pkey->pkey.ptr; |
79 | if (siglen != 64 || |
80 | !ED25519_verify(tbs, tbslen, sig, key->key.pub.value)) { |
81 | OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_SIGNATURE); |
82 | return 0; |
83 | } |
84 | |
85 | return 1; |
86 | } |
87 | |
88 | const EVP_PKEY_METHOD ed25519_pkey_meth = { |
89 | EVP_PKEY_ED25519, |
90 | NULL /* init */, |
91 | pkey_ed25519_copy, |
92 | NULL /* cleanup */, |
93 | pkey_ed25519_keygen, |
94 | NULL /* sign */, |
95 | pkey_ed25519_sign_message, |
96 | NULL /* verify */, |
97 | pkey_ed25519_verify_message, |
98 | NULL /* verify_recover */, |
99 | NULL /* encrypt */, |
100 | NULL /* decrypt */, |
101 | NULL /* derive */, |
102 | NULL /* paramgen */, |
103 | NULL /* ctrl */, |
104 | }; |
105 | |