xref: /freebsd/crypto/openssh/regress/misc/sk-dummy/sk-dummy.c (revision 535af610a4fdace6d50960c0ad9be0597eea7a1b)
119261079SEd Maste /*
219261079SEd Maste  * Copyright (c) 2019 Markus Friedl
319261079SEd Maste  *
419261079SEd Maste  * Permission to use, copy, modify, and distribute this software for any
519261079SEd Maste  * purpose with or without fee is hereby granted, provided that the above
619261079SEd Maste  * copyright notice and this permission notice appear in all copies.
719261079SEd Maste  *
819261079SEd Maste  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
919261079SEd Maste  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1019261079SEd Maste  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1119261079SEd Maste  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1219261079SEd Maste  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1319261079SEd Maste  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1419261079SEd Maste  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1519261079SEd Maste  */
1619261079SEd Maste 
1719261079SEd Maste #include "includes.h"
1819261079SEd Maste 
1919261079SEd Maste #ifdef HAVE_STDINT_H
2019261079SEd Maste #include <stdint.h>
2119261079SEd Maste #endif
2219261079SEd Maste #include <stdlib.h>
2319261079SEd Maste #include <string.h>
2419261079SEd Maste #include <stdio.h>
2519261079SEd Maste #include <stddef.h>
2619261079SEd Maste #include <stdarg.h>
2719261079SEd Maste 
2819261079SEd Maste #include "crypto_api.h"
2919261079SEd Maste #include "sk-api.h"
3019261079SEd Maste 
311323ec57SEd Maste #ifdef WITH_OPENSSL
3219261079SEd Maste #include <openssl/opensslv.h>
33*535af610SEd Maste #include <openssl/sha.h>
3419261079SEd Maste #include <openssl/crypto.h>
3519261079SEd Maste #include <openssl/evp.h>
3619261079SEd Maste #include <openssl/bn.h>
3719261079SEd Maste #include <openssl/ec.h>
3819261079SEd Maste #include <openssl/ecdsa.h>
3919261079SEd Maste #include <openssl/pem.h>
4019261079SEd Maste 
41*535af610SEd Maste /* Use OpenSSL SHA256 instead of libc */
42*535af610SEd Maste #define SHA256Init(x)		SHA256_Init(x)
43*535af610SEd Maste #define SHA256Update(x, y, z)	SHA256_Update(x, y, z)
44*535af610SEd Maste #define SHA256Final(x, y)	SHA256_Final(x, y)
45*535af610SEd Maste #define SHA2_CTX		SHA256_CTX
46*535af610SEd Maste 
47*535af610SEd Maste #elif defined(HAVE_SHA2_H)
48*535af610SEd Maste #include <sha2.h>
491323ec57SEd Maste #endif /* WITH_OPENSSL */
5019261079SEd Maste 
511323ec57SEd Maste /* #define SK_DEBUG 1 */
521323ec57SEd Maste 
5338a52bd3SEd Maste #if SSH_SK_VERSION_MAJOR != 0x000a0000
5419261079SEd Maste # error SK API has changed, sk-dummy.c needs an update
5519261079SEd Maste #endif
5619261079SEd Maste 
5719261079SEd Maste #ifdef SK_DUMMY_INTEGRATE
5819261079SEd Maste # define sk_api_version		ssh_sk_api_version
5919261079SEd Maste # define sk_enroll		ssh_sk_enroll
6019261079SEd Maste # define sk_sign		ssh_sk_sign
6119261079SEd Maste # define sk_load_resident_keys	ssh_sk_load_resident_keys
6219261079SEd Maste #endif /* !SK_STANDALONE */
6319261079SEd Maste 
6419261079SEd Maste static void skdebug(const char *func, const char *fmt, ...)
6519261079SEd Maste     __attribute__((__format__ (printf, 2, 3)));
6619261079SEd Maste 
6719261079SEd Maste static void
skdebug(const char * func,const char * fmt,...)6819261079SEd Maste skdebug(const char *func, const char *fmt, ...)
6919261079SEd Maste {
7019261079SEd Maste #if defined(SK_DEBUG)
7119261079SEd Maste 	va_list ap;
7219261079SEd Maste 
7319261079SEd Maste 	va_start(ap, fmt);
7419261079SEd Maste 	fprintf(stderr, "sk-dummy %s: ", func);
7519261079SEd Maste 	vfprintf(stderr, fmt, ap);
7619261079SEd Maste 	fputc('\n', stderr);
7719261079SEd Maste 	va_end(ap);
7819261079SEd Maste #else
7919261079SEd Maste 	(void)func; /* XXX */
8019261079SEd Maste 	(void)fmt; /* XXX */
8119261079SEd Maste #endif
8219261079SEd Maste }
8319261079SEd Maste 
8419261079SEd Maste uint32_t
sk_api_version(void)8519261079SEd Maste sk_api_version(void)
8619261079SEd Maste {
8719261079SEd Maste 	return SSH_SK_VERSION_MAJOR;
8819261079SEd Maste }
8919261079SEd Maste 
9019261079SEd Maste static int
pack_key_ecdsa(struct sk_enroll_response * response)9119261079SEd Maste pack_key_ecdsa(struct sk_enroll_response *response)
9219261079SEd Maste {
9319261079SEd Maste #ifdef OPENSSL_HAS_ECC
9419261079SEd Maste 	EC_KEY *key = NULL;
9519261079SEd Maste 	const EC_GROUP *g;
9619261079SEd Maste 	const EC_POINT *q;
9719261079SEd Maste 	int ret = -1;
9819261079SEd Maste 	long privlen;
9919261079SEd Maste 	BIO *bio = NULL;
10019261079SEd Maste 	char *privptr;
10119261079SEd Maste 
10219261079SEd Maste 	response->public_key = NULL;
10319261079SEd Maste 	response->public_key_len = 0;
10419261079SEd Maste 	response->key_handle = NULL;
10519261079SEd Maste 	response->key_handle_len = 0;
10619261079SEd Maste 
10719261079SEd Maste 	if ((key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)) == NULL) {
10819261079SEd Maste 		skdebug(__func__, "EC_KEY_new_by_curve_name");
10919261079SEd Maste 		goto out;
11019261079SEd Maste 	}
11119261079SEd Maste 	if (EC_KEY_generate_key(key) != 1) {
11219261079SEd Maste 		skdebug(__func__, "EC_KEY_generate_key");
11319261079SEd Maste 		goto out;
11419261079SEd Maste 	}
11519261079SEd Maste 	EC_KEY_set_asn1_flag(key, OPENSSL_EC_NAMED_CURVE);
11619261079SEd Maste 	if ((bio = BIO_new(BIO_s_mem())) == NULL ||
11719261079SEd Maste 	    (g = EC_KEY_get0_group(key)) == NULL ||
11819261079SEd Maste 	    (q = EC_KEY_get0_public_key(key)) == NULL) {
11919261079SEd Maste 		skdebug(__func__, "couldn't get key parameters");
12019261079SEd Maste 		goto out;
12119261079SEd Maste 	}
12219261079SEd Maste 	response->public_key_len = EC_POINT_point2oct(g, q,
12319261079SEd Maste 	    POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
12419261079SEd Maste 	if (response->public_key_len == 0 || response->public_key_len > 2048) {
12519261079SEd Maste 		skdebug(__func__, "bad pubkey length %zu",
12619261079SEd Maste 		    response->public_key_len);
12719261079SEd Maste 		goto out;
12819261079SEd Maste 	}
12919261079SEd Maste 	if ((response->public_key = malloc(response->public_key_len)) == NULL) {
13019261079SEd Maste 		skdebug(__func__, "malloc pubkey failed");
13119261079SEd Maste 		goto out;
13219261079SEd Maste 	}
13319261079SEd Maste 	if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED,
13419261079SEd Maste 	    response->public_key, response->public_key_len, NULL) == 0) {
13519261079SEd Maste 		skdebug(__func__, "EC_POINT_point2oct failed");
13619261079SEd Maste 		goto out;
13719261079SEd Maste 	}
13819261079SEd Maste 	/* Key handle contains PEM encoded private key */
13919261079SEd Maste 	if (!PEM_write_bio_ECPrivateKey(bio, key, NULL, NULL, 0, NULL, NULL)) {
14019261079SEd Maste 		skdebug(__func__, "PEM_write_bio_ECPrivateKey failed");
14119261079SEd Maste 		goto out;
14219261079SEd Maste 	}
14319261079SEd Maste 	if ((privlen = BIO_get_mem_data(bio, &privptr)) <= 0) {
14419261079SEd Maste 		skdebug(__func__, "BIO_get_mem_data failed");
14519261079SEd Maste 		goto out;
14619261079SEd Maste 	}
14719261079SEd Maste 	if ((response->key_handle = malloc(privlen)) == NULL) {
14819261079SEd Maste 		skdebug(__func__, "malloc key_handle failed");
14919261079SEd Maste 		goto out;
15019261079SEd Maste 	}
15119261079SEd Maste 	response->key_handle_len = (size_t)privlen;
15219261079SEd Maste 	memcpy(response->key_handle, privptr, response->key_handle_len);
15319261079SEd Maste 	/* success */
15419261079SEd Maste 	ret = 0;
15519261079SEd Maste  out:
15619261079SEd Maste 	if (ret != 0) {
15719261079SEd Maste 		if (response->public_key != NULL) {
15819261079SEd Maste 			memset(response->public_key, 0,
15919261079SEd Maste 			    response->public_key_len);
16019261079SEd Maste 			free(response->public_key);
16119261079SEd Maste 			response->public_key = NULL;
16219261079SEd Maste 		}
16319261079SEd Maste 		if (response->key_handle != NULL) {
16419261079SEd Maste 			memset(response->key_handle, 0,
16519261079SEd Maste 			    response->key_handle_len);
16619261079SEd Maste 			free(response->key_handle);
16719261079SEd Maste 			response->key_handle = NULL;
16819261079SEd Maste 		}
16919261079SEd Maste 	}
17019261079SEd Maste 	BIO_free(bio);
17119261079SEd Maste 	EC_KEY_free(key);
17219261079SEd Maste 	return ret;
17319261079SEd Maste #else
17419261079SEd Maste 	return -1;
17519261079SEd Maste #endif
17619261079SEd Maste }
17719261079SEd Maste 
17819261079SEd Maste static int
pack_key_ed25519(struct sk_enroll_response * response)17919261079SEd Maste pack_key_ed25519(struct sk_enroll_response *response)
18019261079SEd Maste {
18119261079SEd Maste 	int ret = -1;
18219261079SEd Maste 	u_char pk[crypto_sign_ed25519_PUBLICKEYBYTES];
18319261079SEd Maste 	u_char sk[crypto_sign_ed25519_SECRETKEYBYTES];
18419261079SEd Maste 
18519261079SEd Maste 	response->public_key = NULL;
18619261079SEd Maste 	response->public_key_len = 0;
18719261079SEd Maste 	response->key_handle = NULL;
18819261079SEd Maste 	response->key_handle_len = 0;
18919261079SEd Maste 
19019261079SEd Maste 	memset(pk, 0, sizeof(pk));
19119261079SEd Maste 	memset(sk, 0, sizeof(sk));
19219261079SEd Maste 	crypto_sign_ed25519_keypair(pk, sk);
19319261079SEd Maste 
19419261079SEd Maste 	response->public_key_len = sizeof(pk);
19519261079SEd Maste 	if ((response->public_key = malloc(response->public_key_len)) == NULL) {
19619261079SEd Maste 		skdebug(__func__, "malloc pubkey failed");
19719261079SEd Maste 		goto out;
19819261079SEd Maste 	}
19919261079SEd Maste 	memcpy(response->public_key, pk, sizeof(pk));
20019261079SEd Maste 	/* Key handle contains sk */
20119261079SEd Maste 	response->key_handle_len = sizeof(sk);
20219261079SEd Maste 	if ((response->key_handle = malloc(response->key_handle_len)) == NULL) {
20319261079SEd Maste 		skdebug(__func__, "malloc key_handle failed");
20419261079SEd Maste 		goto out;
20519261079SEd Maste 	}
20619261079SEd Maste 	memcpy(response->key_handle, sk, sizeof(sk));
20719261079SEd Maste 	/* success */
20819261079SEd Maste 	ret = 0;
20919261079SEd Maste  out:
21019261079SEd Maste 	if (ret != 0)
21119261079SEd Maste 		free(response->public_key);
21219261079SEd Maste 	return ret;
21319261079SEd Maste }
21419261079SEd Maste 
21519261079SEd Maste static int
check_options(struct sk_option ** options)21619261079SEd Maste check_options(struct sk_option **options)
21719261079SEd Maste {
21819261079SEd Maste 	size_t i;
21919261079SEd Maste 
22019261079SEd Maste 	if (options == NULL)
22119261079SEd Maste 		return 0;
22219261079SEd Maste 	for (i = 0; options[i] != NULL; i++) {
22319261079SEd Maste 		skdebug(__func__, "requested unsupported option %s",
22419261079SEd Maste 		    options[i]->name);
22519261079SEd Maste 		if (options[i]->required) {
22619261079SEd Maste 			skdebug(__func__, "unknown required option");
22719261079SEd Maste 			return -1;
22819261079SEd Maste 		}
22919261079SEd Maste 	}
23019261079SEd Maste 	return 0;
23119261079SEd Maste }
23219261079SEd Maste 
23319261079SEd Maste 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)23419261079SEd Maste sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
23519261079SEd Maste     const char *application, uint8_t flags, const char *pin,
23619261079SEd Maste     struct sk_option **options, struct sk_enroll_response **enroll_response)
23719261079SEd Maste {
23819261079SEd Maste 	struct sk_enroll_response *response = NULL;
23919261079SEd Maste 	int ret = SSH_SK_ERR_GENERAL;
24019261079SEd Maste 
24119261079SEd Maste 	(void)flags; /* XXX; unused */
24219261079SEd Maste 
24319261079SEd Maste 	if (enroll_response == NULL) {
24419261079SEd Maste 		skdebug(__func__, "enroll_response == NULL");
24519261079SEd Maste 		goto out;
24619261079SEd Maste 	}
24719261079SEd Maste 	*enroll_response = NULL;
24819261079SEd Maste 	if (check_options(options) != 0)
24919261079SEd Maste 		goto out; /* error already logged */
25019261079SEd Maste 	if ((response = calloc(1, sizeof(*response))) == NULL) {
25119261079SEd Maste 		skdebug(__func__, "calloc response failed");
25219261079SEd Maste 		goto out;
25319261079SEd Maste 	}
2541323ec57SEd Maste 	response->flags = flags;
25519261079SEd Maste 	switch(alg) {
25619261079SEd Maste 	case SSH_SK_ECDSA:
25719261079SEd Maste 		if (pack_key_ecdsa(response) != 0)
25819261079SEd Maste 			goto out;
25919261079SEd Maste 		break;
26019261079SEd Maste 	case SSH_SK_ED25519:
26119261079SEd Maste 		if (pack_key_ed25519(response) != 0)
26219261079SEd Maste 			goto out;
26319261079SEd Maste 		break;
26419261079SEd Maste 	default:
26519261079SEd Maste 		skdebug(__func__, "unsupported key type %d", alg);
26619261079SEd Maste 		return -1;
26719261079SEd Maste 	}
26819261079SEd Maste 	/* Have to return something here */
26919261079SEd Maste 	if ((response->signature = calloc(1, 1)) == NULL) {
27019261079SEd Maste 		skdebug(__func__, "calloc signature failed");
27119261079SEd Maste 		goto out;
27219261079SEd Maste 	}
27319261079SEd Maste 	response->signature_len = 0;
27419261079SEd Maste 
27519261079SEd Maste 	*enroll_response = response;
27619261079SEd Maste 	response = NULL;
27719261079SEd Maste 	ret = 0;
27819261079SEd Maste  out:
27919261079SEd Maste 	if (response != NULL) {
28019261079SEd Maste 		free(response->public_key);
28119261079SEd Maste 		free(response->key_handle);
28219261079SEd Maste 		free(response->signature);
28319261079SEd Maste 		free(response->attestation_cert);
28419261079SEd Maste 		free(response);
28519261079SEd Maste 	}
28619261079SEd Maste 	return ret;
28719261079SEd Maste }
28819261079SEd Maste 
28919261079SEd Maste static void
dump(const char * preamble,const void * sv,size_t l)29019261079SEd Maste dump(const char *preamble, const void *sv, size_t l)
29119261079SEd Maste {
29219261079SEd Maste #ifdef SK_DEBUG
29319261079SEd Maste 	const u_char *s = (const u_char *)sv;
29419261079SEd Maste 	size_t i;
29519261079SEd Maste 
29619261079SEd Maste 	fprintf(stderr, "%s (len %zu):\n", preamble, l);
29719261079SEd Maste 	for (i = 0; i < l; i++) {
29819261079SEd Maste 		if (i % 16 == 0)
29919261079SEd Maste 			fprintf(stderr, "%04zu: ", i);
30019261079SEd Maste 		fprintf(stderr, "%02x", s[i]);
30119261079SEd Maste 		if (i % 16 == 15 || i == l - 1)
30219261079SEd Maste 			fprintf(stderr, "\n");
30319261079SEd Maste 	}
30419261079SEd Maste #endif
30519261079SEd Maste }
30619261079SEd Maste 
30719261079SEd Maste 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)30819261079SEd Maste sig_ecdsa(const uint8_t *message, size_t message_len,
30919261079SEd Maste     const char *application, uint32_t counter, uint8_t flags,
31019261079SEd Maste     const uint8_t *key_handle, size_t key_handle_len,
31119261079SEd Maste     struct sk_sign_response *response)
31219261079SEd Maste {
31319261079SEd Maste #ifdef OPENSSL_HAS_ECC
31419261079SEd Maste 	ECDSA_SIG *sig = NULL;
31519261079SEd Maste 	const BIGNUM *sig_r, *sig_s;
31619261079SEd Maste 	int ret = -1;
31719261079SEd Maste 	BIO *bio = NULL;
31819261079SEd Maste 	EVP_PKEY *pk = NULL;
31919261079SEd Maste 	EC_KEY *ec = NULL;
3201323ec57SEd Maste 	SHA2_CTX ctx;
32119261079SEd Maste 	uint8_t	apphash[SHA256_DIGEST_LENGTH];
32219261079SEd Maste 	uint8_t	sighash[SHA256_DIGEST_LENGTH];
32319261079SEd Maste 	uint8_t countbuf[4];
32419261079SEd Maste 
32519261079SEd Maste 	/* Decode EC_KEY from key handle */
32619261079SEd Maste 	if ((bio = BIO_new(BIO_s_mem())) == NULL ||
32719261079SEd Maste 	    BIO_write(bio, key_handle, key_handle_len) != (int)key_handle_len) {
32819261079SEd Maste 		skdebug(__func__, "BIO setup failed");
32919261079SEd Maste 		goto out;
33019261079SEd Maste 	}
33119261079SEd Maste 	if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, "")) == NULL) {
33219261079SEd Maste 		skdebug(__func__, "PEM_read_bio_PrivateKey failed");
33319261079SEd Maste 		goto out;
33419261079SEd Maste 	}
33519261079SEd Maste 	if (EVP_PKEY_base_id(pk) != EVP_PKEY_EC) {
33619261079SEd Maste 		skdebug(__func__, "Not an EC key: %d", EVP_PKEY_base_id(pk));
33719261079SEd Maste 		goto out;
33819261079SEd Maste 	}
33919261079SEd Maste 	if ((ec = EVP_PKEY_get1_EC_KEY(pk)) == NULL) {
34019261079SEd Maste 		skdebug(__func__, "EVP_PKEY_get1_EC_KEY failed");
34119261079SEd Maste 		goto out;
34219261079SEd Maste 	}
34319261079SEd Maste 	/* Expect message to be pre-hashed */
34419261079SEd Maste 	if (message_len != SHA256_DIGEST_LENGTH) {
34519261079SEd Maste 		skdebug(__func__, "bad message len %zu", message_len);
34619261079SEd Maste 		goto out;
34719261079SEd Maste 	}
34819261079SEd Maste 	/* Prepare data to be signed */
34919261079SEd Maste 	dump("message", message, message_len);
3501323ec57SEd Maste 	SHA256Init(&ctx);
3511323ec57SEd Maste 	SHA256Update(&ctx, (const u_char *)application, strlen(application));
3521323ec57SEd Maste 	SHA256Final(apphash, &ctx);
35319261079SEd Maste 	dump("apphash", apphash, sizeof(apphash));
35419261079SEd Maste 	countbuf[0] = (counter >> 24) & 0xff;
35519261079SEd Maste 	countbuf[1] = (counter >> 16) & 0xff;
35619261079SEd Maste 	countbuf[2] = (counter >> 8) & 0xff;
35719261079SEd Maste 	countbuf[3] = counter & 0xff;
35819261079SEd Maste 	dump("countbuf", countbuf, sizeof(countbuf));
35919261079SEd Maste 	dump("flags", &flags, sizeof(flags));
3601323ec57SEd Maste 	SHA256Init(&ctx);
3611323ec57SEd Maste 	SHA256Update(&ctx, apphash, sizeof(apphash));
3621323ec57SEd Maste 	SHA256Update(&ctx, &flags, sizeof(flags));
3631323ec57SEd Maste 	SHA256Update(&ctx, countbuf, sizeof(countbuf));
3641323ec57SEd Maste 	SHA256Update(&ctx, message, message_len);
3651323ec57SEd Maste 	SHA256Final(sighash, &ctx);
36619261079SEd Maste 	dump("sighash", sighash, sizeof(sighash));
36719261079SEd Maste 	/* create and encode signature */
36819261079SEd Maste 	if ((sig = ECDSA_do_sign(sighash, sizeof(sighash), ec)) == NULL) {
36919261079SEd Maste 		skdebug(__func__, "ECDSA_do_sign failed");
37019261079SEd Maste 		goto out;
37119261079SEd Maste 	}
37219261079SEd Maste 	ECDSA_SIG_get0(sig, &sig_r, &sig_s);
37319261079SEd Maste 	response->sig_r_len = BN_num_bytes(sig_r);
37419261079SEd Maste 	response->sig_s_len = BN_num_bytes(sig_s);
37519261079SEd Maste 	if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL ||
37619261079SEd Maste 	    (response->sig_s = calloc(1, response->sig_s_len)) == NULL) {
37719261079SEd Maste 		skdebug(__func__, "calloc signature failed");
37819261079SEd Maste 		goto out;
37919261079SEd Maste 	}
38019261079SEd Maste 	BN_bn2bin(sig_r, response->sig_r);
38119261079SEd Maste 	BN_bn2bin(sig_s, response->sig_s);
38219261079SEd Maste 	ret = 0;
38319261079SEd Maste  out:
38419261079SEd Maste 	explicit_bzero(&ctx, sizeof(ctx));
38519261079SEd Maste 	explicit_bzero(&apphash, sizeof(apphash));
38619261079SEd Maste 	explicit_bzero(&sighash, sizeof(sighash));
38719261079SEd Maste 	ECDSA_SIG_free(sig);
38819261079SEd Maste 	if (ret != 0) {
38919261079SEd Maste 		free(response->sig_r);
39019261079SEd Maste 		free(response->sig_s);
39119261079SEd Maste 		response->sig_r = NULL;
39219261079SEd Maste 		response->sig_s = NULL;
39319261079SEd Maste 	}
39419261079SEd Maste 	BIO_free(bio);
39519261079SEd Maste 	EC_KEY_free(ec);
39619261079SEd Maste 	EVP_PKEY_free(pk);
39719261079SEd Maste 	return ret;
39819261079SEd Maste #else
39919261079SEd Maste 	return -1;
40019261079SEd Maste #endif
40119261079SEd Maste }
40219261079SEd Maste 
40319261079SEd Maste 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)40419261079SEd Maste sig_ed25519(const uint8_t *message, size_t message_len,
40519261079SEd Maste     const char *application, uint32_t counter, uint8_t flags,
40619261079SEd Maste     const uint8_t *key_handle, size_t key_handle_len,
40719261079SEd Maste     struct sk_sign_response *response)
40819261079SEd Maste {
40919261079SEd Maste 	size_t o;
41019261079SEd Maste 	int ret = -1;
4111323ec57SEd Maste 	SHA2_CTX ctx;
41219261079SEd Maste 	uint8_t	apphash[SHA256_DIGEST_LENGTH];
41319261079SEd Maste 	uint8_t signbuf[sizeof(apphash) + sizeof(flags) +
41419261079SEd Maste 	    sizeof(counter) + SHA256_DIGEST_LENGTH];
41519261079SEd Maste 	uint8_t sig[crypto_sign_ed25519_BYTES + sizeof(signbuf)];
41619261079SEd Maste 	unsigned long long smlen;
41719261079SEd Maste 
41819261079SEd Maste 	if (key_handle_len != crypto_sign_ed25519_SECRETKEYBYTES) {
41919261079SEd Maste 		skdebug(__func__, "bad key handle length %zu", key_handle_len);
42019261079SEd Maste 		goto out;
42119261079SEd Maste 	}
42219261079SEd Maste 	/* Expect message to be pre-hashed */
42319261079SEd Maste 	if (message_len != SHA256_DIGEST_LENGTH) {
42419261079SEd Maste 		skdebug(__func__, "bad message len %zu", message_len);
42519261079SEd Maste 		goto out;
42619261079SEd Maste 	}
42719261079SEd Maste 	/* Prepare data to be signed */
42819261079SEd Maste 	dump("message", message, message_len);
4291323ec57SEd Maste 	SHA256Init(&ctx);
4301323ec57SEd Maste 	SHA256Update(&ctx, (const u_char *)application, strlen(application));
4311323ec57SEd Maste 	SHA256Final(apphash, &ctx);
43219261079SEd Maste 	dump("apphash", apphash, sizeof(apphash));
43319261079SEd Maste 
43419261079SEd Maste 	memcpy(signbuf, apphash, sizeof(apphash));
43519261079SEd Maste 	o = sizeof(apphash);
43619261079SEd Maste 	signbuf[o++] = flags;
43719261079SEd Maste 	signbuf[o++] = (counter >> 24) & 0xff;
43819261079SEd Maste 	signbuf[o++] = (counter >> 16) & 0xff;
43919261079SEd Maste 	signbuf[o++] = (counter >> 8) & 0xff;
44019261079SEd Maste 	signbuf[o++] = counter & 0xff;
44119261079SEd Maste 	memcpy(signbuf + o, message, message_len);
44219261079SEd Maste 	o += message_len;
44319261079SEd Maste 	if (o != sizeof(signbuf)) {
44419261079SEd Maste 		skdebug(__func__, "bad sign buf len %zu, expected %zu",
44519261079SEd Maste 		    o, sizeof(signbuf));
44619261079SEd Maste 		goto out;
44719261079SEd Maste 	}
44819261079SEd Maste 	dump("signbuf", signbuf, sizeof(signbuf));
44919261079SEd Maste 	/* create and encode signature */
45019261079SEd Maste 	smlen = sizeof(signbuf);
45119261079SEd Maste 	if (crypto_sign_ed25519(sig, &smlen, signbuf, sizeof(signbuf),
45219261079SEd Maste 	    key_handle) != 0) {
45319261079SEd Maste 		skdebug(__func__, "crypto_sign_ed25519 failed");
45419261079SEd Maste 		goto out;
45519261079SEd Maste 	}
45619261079SEd Maste 	if (smlen <= sizeof(signbuf)) {
45719261079SEd Maste 		skdebug(__func__, "bad sign smlen %llu, expected min %zu",
45819261079SEd Maste 		    smlen, sizeof(signbuf) + 1);
45919261079SEd Maste 		goto out;
46019261079SEd Maste 	}
46119261079SEd Maste 	response->sig_r_len = (size_t)(smlen - sizeof(signbuf));
46219261079SEd Maste 	if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) {
46319261079SEd Maste 		skdebug(__func__, "calloc signature failed");
46419261079SEd Maste 		goto out;
46519261079SEd Maste 	}
46619261079SEd Maste 	memcpy(response->sig_r, sig, response->sig_r_len);
46719261079SEd Maste 	dump("sig_r", response->sig_r, response->sig_r_len);
46819261079SEd Maste 	ret = 0;
46919261079SEd Maste  out:
47019261079SEd Maste 	explicit_bzero(&ctx, sizeof(ctx));
47119261079SEd Maste 	explicit_bzero(&apphash, sizeof(apphash));
47219261079SEd Maste 	explicit_bzero(&signbuf, sizeof(signbuf));
47319261079SEd Maste 	explicit_bzero(&sig, sizeof(sig));
47419261079SEd Maste 	if (ret != 0) {
47519261079SEd Maste 		free(response->sig_r);
47619261079SEd Maste 		response->sig_r = NULL;
47719261079SEd Maste 	}
47819261079SEd Maste 	return ret;
47919261079SEd Maste }
48019261079SEd Maste 
48119261079SEd Maste 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)48219261079SEd Maste sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
48319261079SEd Maste     const char *application, const uint8_t *key_handle, size_t key_handle_len,
48419261079SEd Maste     uint8_t flags, const char *pin, struct sk_option **options,
48519261079SEd Maste     struct sk_sign_response **sign_response)
48619261079SEd Maste {
48719261079SEd Maste 	struct sk_sign_response *response = NULL;
48819261079SEd Maste 	int ret = SSH_SK_ERR_GENERAL;
4891323ec57SEd Maste 	SHA2_CTX ctx;
49019261079SEd Maste 	uint8_t message[32];
49119261079SEd Maste 
49219261079SEd Maste 	if (sign_response == NULL) {
49319261079SEd Maste 		skdebug(__func__, "sign_response == NULL");
49419261079SEd Maste 		goto out;
49519261079SEd Maste 	}
49619261079SEd Maste 	*sign_response = NULL;
49719261079SEd Maste 	if (check_options(options) != 0)
49819261079SEd Maste 		goto out; /* error already logged */
49919261079SEd Maste 	if ((response = calloc(1, sizeof(*response))) == NULL) {
50019261079SEd Maste 		skdebug(__func__, "calloc response failed");
50119261079SEd Maste 		goto out;
50219261079SEd Maste 	}
5031323ec57SEd Maste 	SHA256Init(&ctx);
5041323ec57SEd Maste 	SHA256Update(&ctx, data, datalen);
5051323ec57SEd Maste 	SHA256Final(message, &ctx);
50619261079SEd Maste 	response->flags = flags;
50719261079SEd Maste 	response->counter = 0x12345678;
50819261079SEd Maste 	switch(alg) {
50919261079SEd Maste 	case SSH_SK_ECDSA:
51019261079SEd Maste 		if (sig_ecdsa(message, sizeof(message), application,
51119261079SEd Maste 		    response->counter, flags, key_handle, key_handle_len,
51219261079SEd Maste 		    response) != 0)
51319261079SEd Maste 			goto out;
51419261079SEd Maste 		break;
51519261079SEd Maste 	case SSH_SK_ED25519:
51619261079SEd Maste 		if (sig_ed25519(message, sizeof(message), application,
51719261079SEd Maste 		    response->counter, flags, key_handle, key_handle_len,
51819261079SEd Maste 		    response) != 0)
51919261079SEd Maste 			goto out;
52019261079SEd Maste 		break;
52119261079SEd Maste 	default:
52219261079SEd Maste 		skdebug(__func__, "unsupported key type %d", alg);
52319261079SEd Maste 		return -1;
52419261079SEd Maste 	}
52519261079SEd Maste 	*sign_response = response;
52619261079SEd Maste 	response = NULL;
52719261079SEd Maste 	ret = 0;
52819261079SEd Maste  out:
52919261079SEd Maste 	explicit_bzero(message, sizeof(message));
53019261079SEd Maste 	if (response != NULL) {
53119261079SEd Maste 		free(response->sig_r);
53219261079SEd Maste 		free(response->sig_s);
53319261079SEd Maste 		free(response);
53419261079SEd Maste 	}
53519261079SEd Maste 	return ret;
53619261079SEd Maste }
53719261079SEd Maste 
53819261079SEd Maste int
sk_load_resident_keys(const char * pin,struct sk_option ** options,struct sk_resident_key *** rks,size_t * nrks)53919261079SEd Maste sk_load_resident_keys(const char *pin, struct sk_option **options,
54019261079SEd Maste     struct sk_resident_key ***rks, size_t *nrks)
54119261079SEd Maste {
54219261079SEd Maste 	return SSH_SK_ERR_UNSUPPORTED;
54319261079SEd Maste }
544