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