wireguard: initial implementation of wireguard protocol
[vpp.git] / src / plugins / wireguard / wireguard_key.c
1 /*
2  * Copyright (c) 2020 Doc.ai and/or its affiliates.
3  * Copyright (c) 2005-2011 Jouni Malinen <j@w1.fi>.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <wireguard/wireguard_key.h>
18 #include <openssl/evp.h>
19
20 bool
21 curve25519_gen_shared (u8 shared_key[CURVE25519_KEY_SIZE],
22                        const u8 secret_key[CURVE25519_KEY_SIZE],
23                        const u8 basepoint[CURVE25519_KEY_SIZE])
24 {
25
26   bool ret;
27   EVP_PKEY_CTX *ctx;
28   size_t key_len;
29
30   EVP_PKEY *peerkey = NULL;
31   EVP_PKEY *pkey =
32     EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, secret_key,
33                                   CURVE25519_KEY_SIZE);
34
35   ret = true;
36
37   ctx = EVP_PKEY_CTX_new (pkey, NULL);
38   if (EVP_PKEY_derive_init (ctx) <= 0)
39     {
40       ret = false;
41       goto out;
42     }
43
44   peerkey =
45     EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, basepoint,
46                                  CURVE25519_KEY_SIZE);
47   if (EVP_PKEY_derive_set_peer (ctx, peerkey) <= 0)
48     {
49       ret = false;
50       goto out;
51     }
52
53   key_len = CURVE25519_KEY_SIZE;
54   if (EVP_PKEY_derive (ctx, shared_key, &key_len) <= 0)
55     {
56       ret = false;
57     }
58
59 out:
60   EVP_PKEY_CTX_free (ctx);
61   EVP_PKEY_free (pkey);
62   EVP_PKEY_free (peerkey);
63   return ret;
64 }
65
66 bool
67 curve25519_gen_public (u8 public_key[CURVE25519_KEY_SIZE],
68                        const u8 secret_key[CURVE25519_KEY_SIZE])
69 {
70   size_t pub_len;
71   EVP_PKEY *pkey =
72     EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, secret_key,
73                                   CURVE25519_KEY_SIZE);
74   pub_len = CURVE25519_KEY_SIZE;
75   if (!EVP_PKEY_get_raw_public_key (pkey, public_key, &pub_len))
76     {
77       EVP_PKEY_free (pkey);
78       return false;
79     }
80   EVP_PKEY_free (pkey);
81   return true;
82 }
83
84 bool
85 curve25519_gen_secret (u8 secret_key[CURVE25519_KEY_SIZE])
86 {
87   size_t secret_len;
88   EVP_PKEY *pkey = NULL;
89   EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_X25519, NULL);
90   EVP_PKEY_keygen_init (pctx);
91   EVP_PKEY_keygen (pctx, &pkey);
92   EVP_PKEY_CTX_free (pctx);
93
94   secret_len = CURVE25519_KEY_SIZE;
95   if (!EVP_PKEY_get_raw_private_key (pkey, secret_key, &secret_len))
96     {
97       EVP_PKEY_free (pkey);
98       return false;
99     }
100   EVP_PKEY_free (pkey);
101   return true;
102 }
103
104 bool
105 key_to_base64 (const u8 * src, size_t src_len, u8 * out)
106 {
107   if (!EVP_EncodeBlock (out, src, src_len))
108     return false;
109   return true;
110 }
111
112 bool
113 key_from_base64 (const u8 * src, size_t src_len, u8 * out)
114 {
115   if (EVP_DecodeBlock (out, src, src_len - 1) <= 0)
116     return false;
117   return true;
118 }
119
120 /*
121  * fd.io coding-style-patch-verification: ON
122  *
123  * Local Variables:
124  * eval: (c-set-style "gnu")
125  * End:
126  */