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