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