1 /*
2  * Copyright (c) 2019 Markus Friedl
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include "includes.h"
18 
19 #ifdef HAVE_STDINT_H
20 #include <stdint.h>
21 #endif
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <stddef.h>
26 #include <stdarg.h>
27 
28 #include "crypto_api.h"
29 #include "sk-api.h"
30 
31 #include <openssl/opensslv.h>
32 #include <openssl/crypto.h>
33 #include <openssl/evp.h>
34 #include <openssl/bn.h>
35 #include <openssl/ec.h>
36 #include <openssl/ecdsa.h>
37 #include <openssl/pem.h>
38 
39 /* #define SK_DEBUG 1 */
40 
41 /* Compatibility with OpenSSH 1.0.x */
42 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
43 #define ECDSA_SIG_get0(sig, pr, ps) \
44 	do { \
45 		(*pr) = sig->r; \
46 		(*ps) = sig->s; \
47 	} while (0)
48 #endif
49 
50 #if SSH_SK_VERSION_MAJOR != 0x00040000
51 # error SK API has changed, sk-dummy.c needs an update
52 #endif
53 
54 static void skdebug(const char *func, const char *fmt, ...)
55     __attribute__((__format__ (printf, 2, 3)));
56 
57 static void
skdebug(const char * func,const char * fmt,...)58 skdebug(const char *func, const char *fmt, ...)
59 {
60 #if defined(SK_DEBUG)
61 	va_list ap;
62 
63 	va_start(ap, fmt);
64 	fprintf(stderr, "sk-dummy %s: ", func);
65 	vfprintf(stderr, fmt, ap);
66 	fputc('\n', stderr);
67 	va_end(ap);
68 #else
69 	(void)func; /* XXX */
70 	(void)fmt; /* XXX */
71 #endif
72 }
73 
74 uint32_t
sk_api_version(void)75 sk_api_version(void)
76 {
77 	return SSH_SK_VERSION_MAJOR;
78 }
79 
80 static int
pack_key_ecdsa(struct sk_enroll_response * response)81 pack_key_ecdsa(struct sk_enroll_response *response)
82 {
83 #ifdef OPENSSL_HAS_ECC
84 	EC_KEY *key = NULL;
85 	const EC_GROUP *g;
86 	const EC_POINT *q;
87 	int ret = -1;
88 	long privlen;
89 	BIO *bio = NULL;
90 	char *privptr;
91 
92 	response->public_key = NULL;
93 	response->public_key_len = 0;
94 	response->key_handle = NULL;
95 	response->key_handle_len = 0;
96 
97 	if ((key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)) == NULL) {
98 		skdebug(__func__, "EC_KEY_new_by_curve_name");
99 		goto out;
100 	}
101 	if (EC_KEY_generate_key(key) != 1) {
102 		skdebug(__func__, "EC_KEY_generate_key");
103 		goto out;
104 	}
105 	EC_KEY_set_asn1_flag(key, OPENSSL_EC_NAMED_CURVE);
106 	if ((bio = BIO_new(BIO_s_mem())) == NULL ||
107 	    (g = EC_KEY_get0_group(key)) == NULL ||
108 	    (q = EC_KEY_get0_public_key(key)) == NULL) {
109 		skdebug(__func__, "couldn't get key parameters");
110 		goto out;
111 	}
112 	response->public_key_len = EC_POINT_point2oct(g, q,
113 	    POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
114 	if (response->public_key_len == 0 || response->public_key_len > 2048) {
115 		skdebug(__func__, "bad pubkey length %zu",
116 		    response->public_key_len);
117 		goto out;
118 	}
119 	if ((response->public_key = malloc(response->public_key_len)) == NULL) {
120 		skdebug(__func__, "malloc pubkey failed");
121 		goto out;
122 	}
123 	if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED,
124 	    response->public_key, response->public_key_len, NULL) == 0) {
125 		skdebug(__func__, "EC_POINT_point2oct failed");
126 		goto out;
127 	}
128 	/* Key handle contains PEM encoded private key */
129 	if (!PEM_write_bio_ECPrivateKey(bio, key, NULL, NULL, 0, NULL, NULL)) {
130 		skdebug(__func__, "PEM_write_bio_ECPrivateKey failed");
131 		goto out;
132 	}
133 	if ((privlen = BIO_get_mem_data(bio, &privptr)) <= 0) {
134 		skdebug(__func__, "BIO_get_mem_data failed");
135 		goto out;
136 	}
137 	if ((response->key_handle = malloc(privlen)) == NULL) {
138 		skdebug(__func__, "malloc key_handle failed");
139 		goto out;
140 	}
141 	response->key_handle_len = (size_t)privlen;
142 	memcpy(response->key_handle, privptr, response->key_handle_len);
143 	/* success */
144 	ret = 0;
145  out:
146 	if (ret != 0) {
147 		if (response->public_key != NULL) {
148 			memset(response->public_key, 0,
149 			    response->public_key_len);
150 			free(response->public_key);
151 			response->public_key = NULL;
152 		}
153 		if (response->key_handle != NULL) {
154 			memset(response->key_handle, 0,
155 			    response->key_handle_len);
156 			free(response->key_handle);
157 			response->key_handle = NULL;
158 		}
159 	}
160 	BIO_free(bio);
161 	EC_KEY_free(key);
162 	return ret;
163 #else
164 	return -1;
165 #endif
166 }
167 
168 static int
pack_key_ed25519(struct sk_enroll_response * response)169 pack_key_ed25519(struct sk_enroll_response *response)
170 {
171 	int ret = -1;
172 	u_char pk[crypto_sign_ed25519_PUBLICKEYBYTES];
173 	u_char sk[crypto_sign_ed25519_SECRETKEYBYTES];
174 
175 	response->public_key = NULL;
176 	response->public_key_len = 0;
177 	response->key_handle = NULL;
178 	response->key_handle_len = 0;
179 
180 	memset(pk, 0, sizeof(pk));
181 	memset(sk, 0, sizeof(sk));
182 	crypto_sign_ed25519_keypair(pk, sk);
183 
184 	response->public_key_len = sizeof(pk);
185 	if ((response->public_key = malloc(response->public_key_len)) == NULL) {
186 		skdebug(__func__, "malloc pubkey failed");
187 		goto out;
188 	}
189 	memcpy(response->public_key, pk, sizeof(pk));
190 	/* Key handle contains sk */
191 	response->key_handle_len = sizeof(sk);
192 	if ((response->key_handle = malloc(response->key_handle_len)) == NULL) {
193 		skdebug(__func__, "malloc key_handle failed");
194 		goto out;
195 	}
196 	memcpy(response->key_handle, sk, sizeof(sk));
197 	/* success */
198 	ret = 0;
199  out:
200 	if (ret != 0)
201 		free(response->public_key);
202 	return ret;
203 }
204 
205 static int
check_options(struct sk_option ** options)206 check_options(struct sk_option **options)
207 {
208 	size_t i;
209 
210 	if (options == NULL)
211 		return 0;
212 	for (i = 0; options[i] != NULL; i++) {
213 		skdebug(__func__, "requested unsupported option %s",
214 		    options[i]->name);
215 		if (options[i]->required) {
216 			skdebug(__func__, "unknown required option");
217 			return -1;
218 		}
219 	}
220 	return 0;
221 }
222 
223 int
sk_enroll(uint32_t alg,const uint8_t * challenge,size_t challenge_len,const char * application,uint8_t flags,const char * pin,struct sk_option ** options,struct sk_enroll_response ** enroll_response)224 sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
225     const char *application, uint8_t flags, const char *pin,
226     struct sk_option **options, struct sk_enroll_response **enroll_response)
227 {
228 	struct sk_enroll_response *response = NULL;
229 	int ret = SSH_SK_ERR_GENERAL;
230 
231 	(void)flags; /* XXX; unused */
232 
233 	if (enroll_response == NULL) {
234 		skdebug(__func__, "enroll_response == NULL");
235 		goto out;
236 	}
237 	*enroll_response = NULL;
238 	if (check_options(options) != 0)
239 		goto out; /* error already logged */
240 	if ((response = calloc(1, sizeof(*response))) == NULL) {
241 		skdebug(__func__, "calloc response failed");
242 		goto out;
243 	}
244 	switch(alg) {
245 	case SSH_SK_ECDSA:
246 		if (pack_key_ecdsa(response) != 0)
247 			goto out;
248 		break;
249 	case SSH_SK_ED25519:
250 		if (pack_key_ed25519(response) != 0)
251 			goto out;
252 		break;
253 	default:
254 		skdebug(__func__, "unsupported key type %d", alg);
255 		return -1;
256 	}
257 	/* Have to return something here */
258 	if ((response->signature = calloc(1, 1)) == NULL) {
259 		skdebug(__func__, "calloc signature failed");
260 		goto out;
261 	}
262 	response->signature_len = 0;
263 
264 	*enroll_response = response;
265 	response = NULL;
266 	ret = 0;
267  out:
268 	if (response != NULL) {
269 		free(response->public_key);
270 		free(response->key_handle);
271 		free(response->signature);
272 		free(response->attestation_cert);
273 		free(response);
274 	}
275 	return ret;
276 }
277 
278 static void
dump(const char * preamble,const void * sv,size_t l)279 dump(const char *preamble, const void *sv, size_t l)
280 {
281 #ifdef SK_DEBUG
282 	const u_char *s = (const u_char *)sv;
283 	size_t i;
284 
285 	fprintf(stderr, "%s (len %zu):\n", preamble, l);
286 	for (i = 0; i < l; i++) {
287 		if (i % 16 == 0)
288 			fprintf(stderr, "%04zu: ", i);
289 		fprintf(stderr, "%02x", s[i]);
290 		if (i % 16 == 15 || i == l - 1)
291 			fprintf(stderr, "\n");
292 	}
293 #endif
294 }
295 
296 static int
sig_ecdsa(const uint8_t * message,size_t message_len,const char * application,uint32_t counter,uint8_t flags,const uint8_t * key_handle,size_t key_handle_len,struct sk_sign_response * response)297 sig_ecdsa(const uint8_t *message, size_t message_len,
298     const char *application, uint32_t counter, uint8_t flags,
299     const uint8_t *key_handle, size_t key_handle_len,
300     struct sk_sign_response *response)
301 {
302 #ifdef OPENSSL_HAS_ECC
303 	ECDSA_SIG *sig = NULL;
304 	const BIGNUM *sig_r, *sig_s;
305 	int ret = -1;
306 	BIO *bio = NULL;
307 	EVP_PKEY *pk = NULL;
308 	EC_KEY *ec = NULL;
309 	SHA256_CTX ctx;
310 	uint8_t	apphash[SHA256_DIGEST_LENGTH];
311 	uint8_t	sighash[SHA256_DIGEST_LENGTH];
312 	uint8_t countbuf[4];
313 
314 	/* Decode EC_KEY from key handle */
315 	if ((bio = BIO_new(BIO_s_mem())) == NULL ||
316 	    BIO_write(bio, key_handle, key_handle_len) != (int)key_handle_len) {
317 		skdebug(__func__, "BIO setup failed");
318 		goto out;
319 	}
320 	if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, "")) == NULL) {
321 		skdebug(__func__, "PEM_read_bio_PrivateKey failed");
322 		goto out;
323 	}
324 	if (EVP_PKEY_base_id(pk) != EVP_PKEY_EC) {
325 		skdebug(__func__, "Not an EC key: %d", EVP_PKEY_base_id(pk));
326 		goto out;
327 	}
328 	if ((ec = EVP_PKEY_get1_EC_KEY(pk)) == NULL) {
329 		skdebug(__func__, "EVP_PKEY_get1_EC_KEY failed");
330 		goto out;
331 	}
332 	/* Expect message to be pre-hashed */
333 	if (message_len != SHA256_DIGEST_LENGTH) {
334 		skdebug(__func__, "bad message len %zu", message_len);
335 		goto out;
336 	}
337 	/* Prepare data to be signed */
338 	dump("message", message, message_len);
339 	SHA256_Init(&ctx);
340 	SHA256_Update(&ctx, application, strlen(application));
341 	SHA256_Final(apphash, &ctx);
342 	dump("apphash", apphash, sizeof(apphash));
343 	countbuf[0] = (counter >> 24) & 0xff;
344 	countbuf[1] = (counter >> 16) & 0xff;
345 	countbuf[2] = (counter >> 8) & 0xff;
346 	countbuf[3] = counter & 0xff;
347 	dump("countbuf", countbuf, sizeof(countbuf));
348 	dump("flags", &flags, sizeof(flags));
349 	SHA256_Init(&ctx);
350 	SHA256_Update(&ctx, apphash, sizeof(apphash));
351 	SHA256_Update(&ctx, &flags, sizeof(flags));
352 	SHA256_Update(&ctx, countbuf, sizeof(countbuf));
353 	SHA256_Update(&ctx, message, message_len);
354 	SHA256_Final(sighash, &ctx);
355 	dump("sighash", sighash, sizeof(sighash));
356 	/* create and encode signature */
357 	if ((sig = ECDSA_do_sign(sighash, sizeof(sighash), ec)) == NULL) {
358 		skdebug(__func__, "ECDSA_do_sign failed");
359 		goto out;
360 	}
361 	ECDSA_SIG_get0(sig, &sig_r, &sig_s);
362 	response->sig_r_len = BN_num_bytes(sig_r);
363 	response->sig_s_len = BN_num_bytes(sig_s);
364 	if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL ||
365 	    (response->sig_s = calloc(1, response->sig_s_len)) == NULL) {
366 		skdebug(__func__, "calloc signature failed");
367 		goto out;
368 	}
369 	BN_bn2bin(sig_r, response->sig_r);
370 	BN_bn2bin(sig_s, response->sig_s);
371 	ret = 0;
372  out:
373 	explicit_bzero(&ctx, sizeof(ctx));
374 	explicit_bzero(&apphash, sizeof(apphash));
375 	explicit_bzero(&sighash, sizeof(sighash));
376 	ECDSA_SIG_free(sig);
377 	if (ret != 0) {
378 		free(response->sig_r);
379 		free(response->sig_s);
380 		response->sig_r = NULL;
381 		response->sig_s = NULL;
382 	}
383 	BIO_free(bio);
384 	EC_KEY_free(ec);
385 	EVP_PKEY_free(pk);
386 	return ret;
387 #else
388 	return -1;
389 #endif
390 }
391 
392 static int
sig_ed25519(const uint8_t * message,size_t message_len,const char * application,uint32_t counter,uint8_t flags,const uint8_t * key_handle,size_t key_handle_len,struct sk_sign_response * response)393 sig_ed25519(const uint8_t *message, size_t message_len,
394     const char *application, uint32_t counter, uint8_t flags,
395     const uint8_t *key_handle, size_t key_handle_len,
396     struct sk_sign_response *response)
397 {
398 	size_t o;
399 	int ret = -1;
400 	SHA256_CTX ctx;
401 	uint8_t	apphash[SHA256_DIGEST_LENGTH];
402 	uint8_t signbuf[sizeof(apphash) + sizeof(flags) +
403 	    sizeof(counter) + SHA256_DIGEST_LENGTH];
404 	uint8_t sig[crypto_sign_ed25519_BYTES + sizeof(signbuf)];
405 	unsigned long long smlen;
406 
407 	if (key_handle_len != crypto_sign_ed25519_SECRETKEYBYTES) {
408 		skdebug(__func__, "bad key handle length %zu", key_handle_len);
409 		goto out;
410 	}
411 	/* Expect message to be pre-hashed */
412 	if (message_len != SHA256_DIGEST_LENGTH) {
413 		skdebug(__func__, "bad message len %zu", message_len);
414 		goto out;
415 	}
416 	/* Prepare data to be signed */
417 	dump("message", message, message_len);
418 	SHA256_Init(&ctx);
419 	SHA256_Update(&ctx, application, strlen(application));
420 	SHA256_Final(apphash, &ctx);
421 	dump("apphash", apphash, sizeof(apphash));
422 
423 	memcpy(signbuf, apphash, sizeof(apphash));
424 	o = sizeof(apphash);
425 	signbuf[o++] = flags;
426 	signbuf[o++] = (counter >> 24) & 0xff;
427 	signbuf[o++] = (counter >> 16) & 0xff;
428 	signbuf[o++] = (counter >> 8) & 0xff;
429 	signbuf[o++] = counter & 0xff;
430 	memcpy(signbuf + o, message, message_len);
431 	o += message_len;
432 	if (o != sizeof(signbuf)) {
433 		skdebug(__func__, "bad sign buf len %zu, expected %zu",
434 		    o, sizeof(signbuf));
435 		goto out;
436 	}
437 	dump("signbuf", signbuf, sizeof(signbuf));
438 	/* create and encode signature */
439 	smlen = sizeof(signbuf);
440 	if (crypto_sign_ed25519(sig, &smlen, signbuf, sizeof(signbuf),
441 	    key_handle) != 0) {
442 		skdebug(__func__, "crypto_sign_ed25519 failed");
443 		goto out;
444 	}
445 	if (smlen <= sizeof(signbuf)) {
446 		skdebug(__func__, "bad sign smlen %llu, expected min %zu",
447 		    smlen, sizeof(signbuf) + 1);
448 		goto out;
449 	}
450 	response->sig_r_len = (size_t)(smlen - sizeof(signbuf));
451 	if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) {
452 		skdebug(__func__, "calloc signature failed");
453 		goto out;
454 	}
455 	memcpy(response->sig_r, sig, response->sig_r_len);
456 	dump("sig_r", response->sig_r, response->sig_r_len);
457 	ret = 0;
458  out:
459 	explicit_bzero(&ctx, sizeof(ctx));
460 	explicit_bzero(&apphash, sizeof(apphash));
461 	explicit_bzero(&signbuf, sizeof(signbuf));
462 	explicit_bzero(&sig, sizeof(sig));
463 	if (ret != 0) {
464 		free(response->sig_r);
465 		response->sig_r = NULL;
466 	}
467 	return ret;
468 }
469 
470 int
sk_sign(uint32_t alg,const uint8_t * message,size_t message_len,const char * application,const uint8_t * key_handle,size_t key_handle_len,uint8_t flags,const char * pin,struct sk_option ** options,struct sk_sign_response ** sign_response)471 sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
472     const char *application, const uint8_t *key_handle, size_t key_handle_len,
473     uint8_t flags, const char *pin, struct sk_option **options,
474     struct sk_sign_response **sign_response)
475 {
476 	struct sk_sign_response *response = NULL;
477 	int ret = SSH_SK_ERR_GENERAL;
478 
479 	if (sign_response == NULL) {
480 		skdebug(__func__, "sign_response == NULL");
481 		goto out;
482 	}
483 	*sign_response = NULL;
484 	if (check_options(options) != 0)
485 		goto out; /* error already logged */
486 	if ((response = calloc(1, sizeof(*response))) == NULL) {
487 		skdebug(__func__, "calloc response failed");
488 		goto out;
489 	}
490 	response->flags = flags;
491 	response->counter = 0x12345678;
492 	switch(alg) {
493 	case SSH_SK_ECDSA:
494 		if (sig_ecdsa(message, message_len, application,
495 		    response->counter, flags, key_handle, key_handle_len,
496 		    response) != 0)
497 			goto out;
498 		break;
499 	case SSH_SK_ED25519:
500 		if (sig_ed25519(message, message_len, application,
501 		    response->counter, flags, key_handle, key_handle_len,
502 		    response) != 0)
503 			goto out;
504 		break;
505 	default:
506 		skdebug(__func__, "unsupported key type %d", alg);
507 		return -1;
508 	}
509 	*sign_response = response;
510 	response = NULL;
511 	ret = 0;
512  out:
513 	if (response != NULL) {
514 		free(response->sig_r);
515 		free(response->sig_s);
516 		free(response);
517 	}
518 	return ret;
519 }
520 
521 int
sk_load_resident_keys(const char * pin,struct sk_option ** options,struct sk_resident_key *** rks,size_t * nrks)522 sk_load_resident_keys(const char *pin, struct sk_option **options,
523     struct sk_resident_key ***rks, size_t *nrks)
524 {
525 	return SSH_SK_ERR_UNSUPPORTED;
526 }
527