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