Coverage Report

Created: 2023-06-07 06:44

/src/dropbear/src/ed25519.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Dropbear - a SSH2 server
3
 * 
4
 * Copyright (c) 2002,2003 Matt Johnston
5
 * All rights reserved.
6
 * 
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 * 
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 * 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
 * SOFTWARE. */
24
25
/* Perform Ed25519 operations on data, including reading keys, signing and
26
 * verification. */
27
28
#include "includes.h"
29
#include "dbutil.h"
30
#include "buffer.h"
31
#include "ssh.h"
32
#include "curve25519.h"
33
#include "ed25519.h"
34
35
#if DROPBEAR_ED25519
36
37
/* Load a public ed25519 key from a buffer, initialising the values.
38
 * The key will have the same format as buf_put_ed25519_key.
39
 * These should be freed with ed25519_key_free.
40
 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
41
int buf_get_ed25519_pub_key(buffer *buf, dropbear_ed25519_key *key,
42
0
  enum signkey_type expect_keytype) {
43
44
45
0
  unsigned int len, typelen;
46
0
  char *keytype = NULL;
47
0
  enum signkey_type buf_keytype;
48
49
0
  TRACE(("enter buf_get_ed25519_pub_key"))
50
0
  dropbear_assert(key != NULL);
51
52
  /* consume and check the key string */
53
0
  keytype = buf_getstring(buf, &typelen);
54
0
  buf_keytype = signkey_type_from_name(keytype, typelen);
55
0
  m_free(keytype);
56
0
  if (buf_keytype != expect_keytype) {
57
0
    TRACE(("leave buf_get_ed25519_pub_key: mismatch key type"))
58
0
    return DROPBEAR_FAILURE;
59
0
  }
60
61
0
  len = buf_getint(buf);
62
0
  if (len != CURVE25519_LEN || buf->len - buf->pos < len) {
63
0
    TRACE(("leave buf_get_ed25519_pub_key: failure"))
64
0
    return DROPBEAR_FAILURE;
65
0
  }
66
67
0
  m_burn(key->priv, CURVE25519_LEN);
68
0
  memcpy(key->pub, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN);
69
0
  buf_incrpos(buf, CURVE25519_LEN);
70
71
0
  TRACE(("leave buf_get_ed25519_pub_key: success"))
72
0
  return DROPBEAR_SUCCESS;
73
0
}
74
75
/* Same as buf_get_ed25519_pub_key, but reads private key at the end.
76
 * Loads a public and private ed25519 key from a buffer
77
 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
78
1
int buf_get_ed25519_priv_key(buffer *buf, dropbear_ed25519_key *key) {
79
80
1
  unsigned int len;
81
82
1
  TRACE(("enter buf_get_ed25519_priv_key"))
83
1
  dropbear_assert(key != NULL);
84
85
1
  buf_incrpos(buf, 4+SSH_SIGNKEY_ED25519_LEN); /* int + "ssh-ed25519" */
86
87
1
  len = buf_getint(buf);
88
1
  if (len != CURVE25519_LEN*2 || buf->len - buf->pos < len) {
89
0
    TRACE(("leave buf_get_ed25519_priv_key: failure"))
90
0
    return DROPBEAR_FAILURE;
91
0
  }
92
93
1
  memcpy(key->priv, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN);
94
1
  buf_incrpos(buf, CURVE25519_LEN);
95
1
  memcpy(key->pub, buf_getptr(buf, CURVE25519_LEN), CURVE25519_LEN);
96
1
  buf_incrpos(buf, CURVE25519_LEN);
97
98
1
  TRACE(("leave buf_get_ed25519_priv_key: success"))
99
1
  return DROPBEAR_SUCCESS;
100
1
}
101
102
/* Clear and free the memory used by a public or private key */
103
1
void ed25519_key_free(dropbear_ed25519_key *key) {
104
105
1
  TRACE2(("enter ed25519_key_free"))
106
107
1
  if (key == NULL) {
108
1
    TRACE2(("leave ed25519_key_free: key == NULL"))
109
1
    return;
110
1
  }
111
0
  m_burn(key->priv, CURVE25519_LEN);
112
0
  m_free(key);
113
114
0
  TRACE2(("leave ed25519_key_free"))
115
0
}
116
117
/* Put the public ed25519 key into the buffer in the required format */
118
0
void buf_put_ed25519_pub_key(buffer *buf, const dropbear_ed25519_key *key) {
119
120
0
  TRACE(("enter buf_put_ed25519_pub_key"))
121
0
  dropbear_assert(key != NULL);
122
123
0
  buf_putstring(buf, SSH_SIGNKEY_ED25519, SSH_SIGNKEY_ED25519_LEN);
124
0
  buf_putstring(buf, key->pub, CURVE25519_LEN);
125
126
0
  TRACE(("leave buf_put_ed25519_pub_key"))
127
0
}
128
129
/* Put the public and private ed25519 key into the buffer in the required format */
130
0
void buf_put_ed25519_priv_key(buffer *buf, const dropbear_ed25519_key *key) {
131
132
0
  TRACE(("enter buf_put_ed25519_priv_key"))
133
0
  dropbear_assert(key != NULL);
134
135
0
  buf_putstring(buf, SSH_SIGNKEY_ED25519, SSH_SIGNKEY_ED25519_LEN);
136
0
  buf_putint(buf, CURVE25519_LEN*2);
137
0
  buf_putbytes(buf, key->priv, CURVE25519_LEN);
138
0
  buf_putbytes(buf, key->pub, CURVE25519_LEN);
139
140
0
  TRACE(("leave buf_put_ed25519_priv_key"))
141
0
}
142
143
/* Sign the data presented with key, writing the signature contents
144
 * to the buffer */
145
0
void buf_put_ed25519_sign(buffer* buf, const dropbear_ed25519_key *key, const buffer *data_buf) {
146
147
0
  unsigned char s[64];
148
0
  unsigned long slen = sizeof(s);
149
150
0
  TRACE(("enter buf_put_ed25519_sign"))
151
0
  dropbear_assert(key != NULL);
152
153
0
  dropbear_ed25519_sign(data_buf->data, data_buf->len, s, &slen, key->priv, key->pub);
154
0
  buf_putstring(buf, SSH_SIGNKEY_ED25519, SSH_SIGNKEY_ED25519_LEN);
155
0
  buf_putstring(buf, s, slen);
156
157
0
  TRACE(("leave buf_put_ed25519_sign"))
158
0
}
159
160
#if DROPBEAR_SIGNKEY_VERIFY
161
/* Verify a signature in buf, made on data by the key given.
162
 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
163
0
int buf_ed25519_verify(buffer *buf, const dropbear_ed25519_key *key, const buffer *data_buf) {
164
165
0
  int ret = DROPBEAR_FAILURE;
166
0
  unsigned char *s;
167
0
  unsigned long slen;
168
169
0
  TRACE(("enter buf_ed25519_verify"))
170
0
  dropbear_assert(key != NULL);
171
172
0
  slen = buf_getint(buf);
173
0
  if (slen != 64 || buf->len - buf->pos < slen) {
174
0
    TRACE(("leave buf_ed25519_verify: bad size"))
175
0
    goto out;
176
0
  }
177
0
  s = buf_getptr(buf, slen);
178
179
0
  if (dropbear_ed25519_verify(data_buf->data, data_buf->len,
180
0
            s, slen, key->pub) == 0) {
181
    /* signature is valid */
182
0
    TRACE(("leave buf_ed25519_verify: success!"))
183
0
    ret = DROPBEAR_SUCCESS;
184
0
  }
185
186
0
out:
187
0
  TRACE(("leave buf_ed25519_verify: ret %d", ret))
188
0
  return ret;
189
0
}
190
191
#endif /* DROPBEAR_SIGNKEY_VERIFY */
192
193
#endif /* DROPBEAR_ED25519 */