1 /* 2 * Copyright (c) 2018 Yubico AB. All rights reserved. 3 * Use of this source code is governed by a BSD-style 4 * license that can be found in the LICENSE file. 5 */ 6 7 #include <sys/types.h> 8 #include <sys/stat.h> 9 10 #include <openssl/ec.h> 11 #include <openssl/evp.h> 12 #include <openssl/pem.h> 13 14 #include <fido.h> 15 #include <fido/es256.h> 16 #include <fido/rs256.h> 17 #include <fido/eddsa.h> 18 19 #include <errno.h> 20 #include <fcntl.h> 21 #include <limits.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #ifdef HAVE_UNISTD_H 25 #include <unistd.h> 26 #endif 27 #ifdef _MSC_VER 28 #include "../openbsd-compat/posix_win.h" 29 #endif 30 #include "../openbsd-compat/openbsd-compat.h" 31 #include "extern.h" 32 33 int 34 base10(const char *str, long long *ll) 35 { 36 char *ep; 37 38 *ll = strtoll(str, &ep, 10); 39 if (str == ep || *ep != '\0') 40 return (-1); 41 else if (*ll == LLONG_MIN && errno == ERANGE) 42 return (-1); 43 else if (*ll == LLONG_MAX && errno == ERANGE) 44 return (-1); 45 46 return (0); 47 } 48 49 int 50 write_blob(const char *path, const unsigned char *ptr, size_t len) 51 { 52 int fd, ok = -1; 53 ssize_t n; 54 55 if ((fd = open(path, O_WRONLY | O_CREAT, 0600)) < 0) { 56 warn("open %s", path); 57 goto fail; 58 } 59 60 if ((n = write(fd, ptr, len)) < 0) { 61 warn("write"); 62 goto fail; 63 } 64 if ((size_t)n != len) { 65 warnx("write"); 66 goto fail; 67 } 68 69 ok = 0; 70 fail: 71 if (fd != -1) { 72 close(fd); 73 } 74 75 return (ok); 76 } 77 78 int 79 read_blob(const char *path, unsigned char **ptr, size_t *len) 80 { 81 int fd, ok = -1; 82 struct stat st; 83 ssize_t n; 84 85 *ptr = NULL; 86 *len = 0; 87 88 if ((fd = open(path, O_RDONLY)) < 0) { 89 warn("open %s", path); 90 goto fail; 91 } 92 if (fstat(fd, &st) < 0) { 93 warn("stat %s", path); 94 goto fail; 95 } 96 if (st.st_size < 0) { 97 warnx("stat %s: invalid size", path); 98 goto fail; 99 } 100 *len = (size_t)st.st_size; 101 if ((*ptr = malloc(*len)) == NULL) { 102 warn("malloc"); 103 goto fail; 104 } 105 if ((n = read(fd, *ptr, *len)) < 0) { 106 warn("read"); 107 goto fail; 108 } 109 if ((size_t)n != *len) { 110 warnx("read"); 111 goto fail; 112 } 113 114 ok = 0; 115 fail: 116 if (fd != -1) { 117 close(fd); 118 } 119 if (ok < 0) { 120 free(*ptr); 121 *ptr = NULL; 122 *len = 0; 123 } 124 125 return (ok); 126 } 127 128 EC_KEY * 129 read_ec_pubkey(const char *path) 130 { 131 FILE *fp = NULL; 132 EVP_PKEY *pkey = NULL; 133 EC_KEY *ec = NULL; 134 135 if ((fp = fopen(path, "r")) == NULL) { 136 warn("fopen"); 137 goto fail; 138 } 139 140 if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) { 141 warnx("PEM_read_PUBKEY"); 142 goto fail; 143 } 144 if ((ec = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) { 145 warnx("EVP_PKEY_get1_EC_KEY"); 146 goto fail; 147 } 148 149 fail: 150 if (fp != NULL) { 151 fclose(fp); 152 } 153 if (pkey != NULL) { 154 EVP_PKEY_free(pkey); 155 } 156 157 return (ec); 158 } 159 160 int 161 write_ec_pubkey(const char *path, const void *ptr, size_t len) 162 { 163 FILE *fp = NULL; 164 EVP_PKEY *pkey = NULL; 165 es256_pk_t *pk = NULL; 166 int fd = -1; 167 int ok = -1; 168 169 if ((pk = es256_pk_new()) == NULL) { 170 warnx("es256_pk_new"); 171 goto fail; 172 } 173 174 if (es256_pk_from_ptr(pk, ptr, len) != FIDO_OK) { 175 warnx("es256_pk_from_ptr"); 176 goto fail; 177 } 178 179 if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) < 0) { 180 warn("open %s", path); 181 goto fail; 182 } 183 184 if ((fp = fdopen(fd, "w")) == NULL) { 185 warn("fdopen"); 186 goto fail; 187 } 188 fd = -1; /* owned by fp now */ 189 190 if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL) { 191 warnx("es256_pk_to_EVP_PKEY"); 192 goto fail; 193 } 194 195 if (PEM_write_PUBKEY(fp, pkey) == 0) { 196 warnx("PEM_write_PUBKEY"); 197 goto fail; 198 } 199 200 ok = 0; 201 fail: 202 es256_pk_free(&pk); 203 204 if (fp != NULL) { 205 fclose(fp); 206 } 207 if (fd != -1) { 208 close(fd); 209 } 210 if (pkey != NULL) { 211 EVP_PKEY_free(pkey); 212 } 213 214 return (ok); 215 } 216 217 RSA * 218 read_rsa_pubkey(const char *path) 219 { 220 FILE *fp = NULL; 221 EVP_PKEY *pkey = NULL; 222 RSA *rsa = NULL; 223 224 if ((fp = fopen(path, "r")) == NULL) { 225 warn("fopen"); 226 goto fail; 227 } 228 229 if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) { 230 warnx("PEM_read_PUBKEY"); 231 goto fail; 232 } 233 if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) { 234 warnx("EVP_PKEY_get1_RSA"); 235 goto fail; 236 } 237 238 fail: 239 if (fp != NULL) { 240 fclose(fp); 241 } 242 if (pkey != NULL) { 243 EVP_PKEY_free(pkey); 244 } 245 246 return (rsa); 247 } 248 249 int 250 write_rsa_pubkey(const char *path, const void *ptr, size_t len) 251 { 252 FILE *fp = NULL; 253 EVP_PKEY *pkey = NULL; 254 rs256_pk_t *pk = NULL; 255 int fd = -1; 256 int ok = -1; 257 258 if ((pk = rs256_pk_new()) == NULL) { 259 warnx("rs256_pk_new"); 260 goto fail; 261 } 262 263 if (rs256_pk_from_ptr(pk, ptr, len) != FIDO_OK) { 264 warnx("rs256_pk_from_ptr"); 265 goto fail; 266 } 267 268 if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) < 0) { 269 warn("open %s", path); 270 goto fail; 271 } 272 273 if ((fp = fdopen(fd, "w")) == NULL) { 274 warn("fdopen"); 275 goto fail; 276 } 277 fd = -1; /* owned by fp now */ 278 279 if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL) { 280 warnx("rs256_pk_to_EVP_PKEY"); 281 goto fail; 282 } 283 284 if (PEM_write_PUBKEY(fp, pkey) == 0) { 285 warnx("PEM_write_PUBKEY"); 286 goto fail; 287 } 288 289 ok = 0; 290 fail: 291 rs256_pk_free(&pk); 292 293 if (fp != NULL) { 294 fclose(fp); 295 } 296 if (fd != -1) { 297 close(fd); 298 } 299 if (pkey != NULL) { 300 EVP_PKEY_free(pkey); 301 } 302 303 return (ok); 304 } 305 306 EVP_PKEY * 307 read_eddsa_pubkey(const char *path) 308 { 309 FILE *fp = NULL; 310 EVP_PKEY *pkey = NULL; 311 312 if ((fp = fopen(path, "r")) == NULL) { 313 warn("fopen"); 314 goto fail; 315 } 316 317 if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) { 318 warnx("PEM_read_PUBKEY"); 319 goto fail; 320 } 321 322 fail: 323 if (fp) { 324 fclose(fp); 325 } 326 327 return (pkey); 328 } 329 330 int 331 write_eddsa_pubkey(const char *path, const void *ptr, size_t len) 332 { 333 FILE *fp = NULL; 334 EVP_PKEY *pkey = NULL; 335 eddsa_pk_t *pk = NULL; 336 int fd = -1; 337 int ok = -1; 338 339 if ((pk = eddsa_pk_new()) == NULL) { 340 warnx("eddsa_pk_new"); 341 goto fail; 342 } 343 344 if (eddsa_pk_from_ptr(pk, ptr, len) != FIDO_OK) { 345 warnx("eddsa_pk_from_ptr"); 346 goto fail; 347 } 348 349 if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) < 0) { 350 warn("open %s", path); 351 goto fail; 352 } 353 354 if ((fp = fdopen(fd, "w")) == NULL) { 355 warn("fdopen"); 356 goto fail; 357 } 358 fd = -1; /* owned by fp now */ 359 360 if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL) { 361 warnx("eddsa_pk_to_EVP_PKEY"); 362 goto fail; 363 } 364 365 if (PEM_write_PUBKEY(fp, pkey) == 0) { 366 warnx("PEM_write_PUBKEY"); 367 goto fail; 368 } 369 370 ok = 0; 371 fail: 372 eddsa_pk_free(&pk); 373 374 if (fp != NULL) { 375 fclose(fp); 376 } 377 if (fd != -1) { 378 close(fd); 379 } 380 if (pkey != NULL) { 381 EVP_PKEY_free(pkey); 382 } 383 384 return (ok); 385 } 386