=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/ssh-keygen.c,v retrieving revision 1.318 retrieving revision 1.320 diff -u -r1.318 -r1.320 --- src/usr.bin/ssh/ssh-keygen.c 2018/07/09 21:59:10 1.318 +++ src/usr.bin/ssh/ssh-keygen.c 2018/09/12 01:21:34 1.320 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.318 2018/07/09 21:59:10 markus Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.320 2018/09/12 01:21:34 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -172,7 +172,7 @@ char *pkcs11provider = NULL; /* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */ -int use_new_format = 0; +int use_new_format = 1; /* Cipher for new-format private keys */ char *new_format_cipher = NULL; @@ -2064,15 +2064,51 @@ } static void +hash_to_blob(const char *cp, u_char **blobp, size_t *lenp, + const char *file, u_long lnum) +{ + char *tmp; + size_t tlen; + struct sshbuf *b; + int r; + + if (strncmp(cp, "SHA256:", 7) != 0) + fatal("%s:%lu: unsupported hash algorithm", file, lnum); + cp += 7; + + /* + * OpenSSH base64 hashes omit trailing '=' + * characters; put them back for decode. + */ + tlen = strlen(cp); + tmp = xmalloc(tlen + 4 + 1); + strlcpy(tmp, cp, tlen + 1); + while ((tlen % 4) != 0) { + tmp[tlen++] = '='; + tmp[tlen] = '\0'; + } + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + if ((r = sshbuf_b64tod(b, tmp)) != 0) + fatal("%s:%lu: decode hash failed: %s", file, lnum, ssh_err(r)); + free(tmp); + *lenp = sshbuf_len(b); + *blobp = xmalloc(*lenp); + memcpy(*blobp, sshbuf_ptr(b), *lenp); + sshbuf_free(b); +} + +static void update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, const struct sshkey *ca, struct ssh_krl *krl) { struct sshkey *key = NULL; u_long lnum = 0; char *path, *cp, *ep, *line = NULL; - size_t linesize = 0; + u_char *blob = NULL; + size_t blen = 0, linesize = 0; unsigned long long serial, serial2; - int i, was_explicit_key, was_sha1, r; + int i, was_explicit_key, was_sha1, was_sha256, was_hash, r; FILE *krl_spec; path = tilde_expand_filename(file, pw->pw_uid); @@ -2087,7 +2123,7 @@ printf("Revoking from %s\n", path); while (getline(&line, &linesize, krl_spec) != -1) { lnum++; - was_explicit_key = was_sha1 = 0; + was_explicit_key = was_sha1 = was_sha256 = was_hash = 0; cp = line + strspn(line, " \t"); /* Trim trailing space, comments and strip \n */ for (i = 0, r = -1; cp[i] != '\0'; i++) { @@ -2152,6 +2188,11 @@ cp = cp + strspn(cp, " \t"); if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0) fatal("%s: revoke key ID failed", __func__); + } else if (strncasecmp(cp, "hash:", 5) == 0) { + cp += 5; + cp = cp + strspn(cp, " \t"); + hash_to_blob(cp, &blob, &blen, file, lnum); + r = ssh_krl_revoke_key_sha256(krl, blob, blen); } else { if (strncasecmp(cp, "key:", 4) == 0) { cp += 4; @@ -2161,7 +2202,10 @@ cp += 5; cp = cp + strspn(cp, " \t"); was_sha1 = 1; - } else { + } else if (strncasecmp(cp, "sha256:", 7) == 0) { + cp += 7; + cp = cp + strspn(cp, " \t"); + was_sha256 = 1; /* * Just try to process the line as a key. * Parsing will fail if it isn't. @@ -2174,13 +2218,28 @@ path, lnum, ssh_err(r)); if (was_explicit_key) r = ssh_krl_revoke_key_explicit(krl, key); - else if (was_sha1) - r = ssh_krl_revoke_key_sha1(krl, key); - else + else if (was_sha1) { + if (sshkey_fingerprint_raw(key, + SSH_DIGEST_SHA1, &blob, &blen) != 0) { + fatal("%s:%lu: fingerprint failed", + file, lnum); + } + r = ssh_krl_revoke_key_sha1(krl, blob, blen); + } else if (was_sha256) { + if (sshkey_fingerprint_raw(key, + SSH_DIGEST_SHA256, &blob, &blen) != 0) { + fatal("%s:%lu: fingerprint failed", + file, lnum); + } + r = ssh_krl_revoke_key_sha256(krl, blob, blen); + } else r = ssh_krl_revoke_key(krl, key); if (r != 0) fatal("%s: revoke key failed: %s", __func__, ssh_err(r)); + freezero(blob, blen); + blob = NULL; + blen = 0; sshkey_free(key); } } @@ -2413,6 +2472,7 @@ } if (strcasecmp(optarg, "PEM") == 0) { convert_format = FMT_PEM; + use_new_format = 0; break; } fatal("Unsupported conversion format \"%s\"", optarg); @@ -2420,7 +2480,7 @@ cert_principals = optarg; break; case 'o': - use_new_format = 1; + /* no-op; new format is already the default */ break; case 'p': change_passphrase = 1;