1 /* $OpenBSD: kexc25519.c,v 1.17 2019/01/21 10:40:11 djm Exp $ */
3 * Copyright (c) 2019 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved.
5 * Copyright (c) 2013 Aris Adamantiadis. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/types.h>
43 extern int crypto_scalarmult_curve25519(u_char a
[CURVE25519_SIZE
],
44 const u_char b
[CURVE25519_SIZE
], const u_char c
[CURVE25519_SIZE
])
45 __attribute__((__bounded__(__minbytes__
, 1, CURVE25519_SIZE
)))
46 __attribute__((__bounded__(__minbytes__
, 2, CURVE25519_SIZE
)))
47 __attribute__((__bounded__(__minbytes__
, 3, CURVE25519_SIZE
)));
50 kexc25519_keygen(u_char key
[CURVE25519_SIZE
], u_char pub
[CURVE25519_SIZE
])
52 static const u_char basepoint
[CURVE25519_SIZE
] = {9};
54 arc4random_buf(key
, CURVE25519_SIZE
);
55 crypto_scalarmult_curve25519(pub
, key
, basepoint
);
59 kexc25519_shared_key_ext(const u_char key
[CURVE25519_SIZE
],
60 const u_char pub
[CURVE25519_SIZE
], struct sshbuf
*out
, int raw
)
62 u_char shared_key
[CURVE25519_SIZE
];
63 u_char zero
[CURVE25519_SIZE
];
66 crypto_scalarmult_curve25519(shared_key
, key
, pub
);
68 /* Check for all-zero shared secret */
69 explicit_bzero(zero
, CURVE25519_SIZE
);
70 if (timingsafe_bcmp(zero
, shared_key
, CURVE25519_SIZE
) == 0)
71 return SSH_ERR_KEY_INVALID_EC_VALUE
;
74 dump_digest("shared secret", shared_key
, CURVE25519_SIZE
);
77 r
= sshbuf_put(out
, shared_key
, CURVE25519_SIZE
);
79 r
= sshbuf_put_bignum2_bytes(out
, shared_key
, CURVE25519_SIZE
);
80 explicit_bzero(shared_key
, CURVE25519_SIZE
);
85 kexc25519_shared_key(const u_char key
[CURVE25519_SIZE
],
86 const u_char pub
[CURVE25519_SIZE
], struct sshbuf
*out
)
88 return kexc25519_shared_key_ext(key
, pub
, out
, 0);
92 kex_c25519_keypair(struct kex
*kex
)
94 struct sshbuf
*buf
= NULL
;
98 if ((buf
= sshbuf_new()) == NULL
)
99 return SSH_ERR_ALLOC_FAIL
;
100 if ((r
= sshbuf_reserve(buf
, CURVE25519_SIZE
, &cp
)) != 0)
102 kexc25519_keygen(kex
->c25519_client_key
, cp
);
104 dump_digest("client public key c25519:", cp
, CURVE25519_SIZE
);
106 kex
->client_pub
= buf
;
114 kex_c25519_enc(struct kex
*kex
, const struct sshbuf
*client_blob
,
115 struct sshbuf
**server_blobp
, struct sshbuf
**shared_secretp
)
117 struct sshbuf
*server_blob
= NULL
;
118 struct sshbuf
*buf
= NULL
;
119 const u_char
*client_pub
;
121 u_char server_key
[CURVE25519_SIZE
];
124 *server_blobp
= NULL
;
125 *shared_secretp
= NULL
;
127 if (sshbuf_len(client_blob
) != CURVE25519_SIZE
) {
128 r
= SSH_ERR_SIGNATURE_INVALID
;
131 client_pub
= sshbuf_ptr(client_blob
);
133 dump_digest("client public key 25519:", client_pub
, CURVE25519_SIZE
);
135 /* allocate space for encrypted KEM key and ECDH pub key */
136 if ((server_blob
= sshbuf_new()) == NULL
) {
137 r
= SSH_ERR_ALLOC_FAIL
;
140 if ((r
= sshbuf_reserve(server_blob
, CURVE25519_SIZE
, &server_pub
)) != 0)
142 kexc25519_keygen(server_key
, server_pub
);
143 /* allocate shared secret */
144 if ((buf
= sshbuf_new()) == NULL
) {
145 r
= SSH_ERR_ALLOC_FAIL
;
148 if ((r
= kexc25519_shared_key_ext(server_key
, client_pub
, buf
, 0)) < 0)
151 dump_digest("server public key 25519:", server_pub
, CURVE25519_SIZE
);
152 dump_digest("encoded shared secret:", sshbuf_ptr(buf
), sshbuf_len(buf
));
154 *server_blobp
= server_blob
;
155 *shared_secretp
= buf
;
159 explicit_bzero(server_key
, sizeof(server_key
));
160 sshbuf_free(server_blob
);
166 kex_c25519_dec(struct kex
*kex
, const struct sshbuf
*server_blob
,
167 struct sshbuf
**shared_secretp
)
169 struct sshbuf
*buf
= NULL
;
170 const u_char
*server_pub
;
173 *shared_secretp
= NULL
;
175 if (sshbuf_len(server_blob
) != CURVE25519_SIZE
) {
176 r
= SSH_ERR_SIGNATURE_INVALID
;
179 server_pub
= sshbuf_ptr(server_blob
);
181 dump_digest("server public key c25519:", server_pub
, CURVE25519_SIZE
);
184 if ((buf
= sshbuf_new()) == NULL
) {
185 r
= SSH_ERR_ALLOC_FAIL
;
188 if ((r
= kexc25519_shared_key_ext(kex
->c25519_client_key
, server_pub
,
192 dump_digest("encoded shared secret:", sshbuf_ptr(buf
), sshbuf_len(buf
));
194 *shared_secretp
= buf
;