diff options
Diffstat (limited to 'key.c')
-rw-r--r-- | key.c | 595 |
1 files changed, 561 insertions, 34 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: key.c,v 1.82 2010/01/13 01:10:56 dtucker Exp $ */ | 1 | /* $OpenBSD: key.c,v 1.83 2010/02/26 20:29:54 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * read_bignum(): | 3 | * read_bignum(): |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -52,6 +52,21 @@ | |||
52 | #include "uuencode.h" | 52 | #include "uuencode.h" |
53 | #include "buffer.h" | 53 | #include "buffer.h" |
54 | #include "log.h" | 54 | #include "log.h" |
55 | #include "ssh2.h" | ||
56 | |||
57 | static struct KeyCert * | ||
58 | cert_new(void) | ||
59 | { | ||
60 | struct KeyCert *cert; | ||
61 | |||
62 | cert = xcalloc(1, sizeof(*cert)); | ||
63 | buffer_init(&cert->certblob); | ||
64 | buffer_init(&cert->constraints); | ||
65 | cert->key_id = NULL; | ||
66 | cert->principals = NULL; | ||
67 | cert->signature_key = NULL; | ||
68 | return cert; | ||
69 | } | ||
55 | 70 | ||
56 | Key * | 71 | Key * |
57 | key_new(int type) | 72 | key_new(int type) |
@@ -63,9 +78,11 @@ key_new(int type) | |||
63 | k->type = type; | 78 | k->type = type; |
64 | k->dsa = NULL; | 79 | k->dsa = NULL; |
65 | k->rsa = NULL; | 80 | k->rsa = NULL; |
81 | k->cert = NULL; | ||
66 | switch (k->type) { | 82 | switch (k->type) { |
67 | case KEY_RSA1: | 83 | case KEY_RSA1: |
68 | case KEY_RSA: | 84 | case KEY_RSA: |
85 | case KEY_RSA_CERT: | ||
69 | if ((rsa = RSA_new()) == NULL) | 86 | if ((rsa = RSA_new()) == NULL) |
70 | fatal("key_new: RSA_new failed"); | 87 | fatal("key_new: RSA_new failed"); |
71 | if ((rsa->n = BN_new()) == NULL) | 88 | if ((rsa->n = BN_new()) == NULL) |
@@ -75,6 +92,7 @@ key_new(int type) | |||
75 | k->rsa = rsa; | 92 | k->rsa = rsa; |
76 | break; | 93 | break; |
77 | case KEY_DSA: | 94 | case KEY_DSA: |
95 | case KEY_DSA_CERT: | ||
78 | if ((dsa = DSA_new()) == NULL) | 96 | if ((dsa = DSA_new()) == NULL) |
79 | fatal("key_new: DSA_new failed"); | 97 | fatal("key_new: DSA_new failed"); |
80 | if ((dsa->p = BN_new()) == NULL) | 98 | if ((dsa->p = BN_new()) == NULL) |
@@ -93,16 +111,20 @@ key_new(int type) | |||
93 | fatal("key_new: bad key type %d", k->type); | 111 | fatal("key_new: bad key type %d", k->type); |
94 | break; | 112 | break; |
95 | } | 113 | } |
114 | |||
115 | if (key_is_cert(k)) | ||
116 | k->cert = cert_new(); | ||
117 | |||
96 | return k; | 118 | return k; |
97 | } | 119 | } |
98 | 120 | ||
99 | Key * | 121 | void |
100 | key_new_private(int type) | 122 | key_add_private(Key *k) |
101 | { | 123 | { |
102 | Key *k = key_new(type); | ||
103 | switch (k->type) { | 124 | switch (k->type) { |
104 | case KEY_RSA1: | 125 | case KEY_RSA1: |
105 | case KEY_RSA: | 126 | case KEY_RSA: |
127 | case KEY_RSA_CERT: | ||
106 | if ((k->rsa->d = BN_new()) == NULL) | 128 | if ((k->rsa->d = BN_new()) == NULL) |
107 | fatal("key_new_private: BN_new failed"); | 129 | fatal("key_new_private: BN_new failed"); |
108 | if ((k->rsa->iqmp = BN_new()) == NULL) | 130 | if ((k->rsa->iqmp = BN_new()) == NULL) |
@@ -117,6 +139,7 @@ key_new_private(int type) | |||
117 | fatal("key_new_private: BN_new failed"); | 139 | fatal("key_new_private: BN_new failed"); |
118 | break; | 140 | break; |
119 | case KEY_DSA: | 141 | case KEY_DSA: |
142 | case KEY_DSA_CERT: | ||
120 | if ((k->dsa->priv_key = BN_new()) == NULL) | 143 | if ((k->dsa->priv_key = BN_new()) == NULL) |
121 | fatal("key_new_private: BN_new failed"); | 144 | fatal("key_new_private: BN_new failed"); |
122 | break; | 145 | break; |
@@ -125,9 +148,34 @@ key_new_private(int type) | |||
125 | default: | 148 | default: |
126 | break; | 149 | break; |
127 | } | 150 | } |
151 | } | ||
152 | |||
153 | Key * | ||
154 | key_new_private(int type) | ||
155 | { | ||
156 | Key *k = key_new(type); | ||
157 | |||
158 | key_add_private(k); | ||
128 | return k; | 159 | return k; |
129 | } | 160 | } |
130 | 161 | ||
162 | static void | ||
163 | cert_free(struct KeyCert *cert) | ||
164 | { | ||
165 | u_int i; | ||
166 | |||
167 | buffer_free(&cert->certblob); | ||
168 | buffer_free(&cert->constraints); | ||
169 | if (cert->key_id != NULL) | ||
170 | xfree(cert->key_id); | ||
171 | for (i = 0; i < cert->nprincipals; i++) | ||
172 | xfree(cert->principals[i]); | ||
173 | if (cert->principals != NULL) | ||
174 | xfree(cert->principals); | ||
175 | if (cert->signature_key != NULL) | ||
176 | key_free(cert->signature_key); | ||
177 | } | ||
178 | |||
131 | void | 179 | void |
132 | key_free(Key *k) | 180 | key_free(Key *k) |
133 | { | 181 | { |
@@ -136,11 +184,13 @@ key_free(Key *k) | |||
136 | switch (k->type) { | 184 | switch (k->type) { |
137 | case KEY_RSA1: | 185 | case KEY_RSA1: |
138 | case KEY_RSA: | 186 | case KEY_RSA: |
187 | case KEY_RSA_CERT: | ||
139 | if (k->rsa != NULL) | 188 | if (k->rsa != NULL) |
140 | RSA_free(k->rsa); | 189 | RSA_free(k->rsa); |
141 | k->rsa = NULL; | 190 | k->rsa = NULL; |
142 | break; | 191 | break; |
143 | case KEY_DSA: | 192 | case KEY_DSA: |
193 | case KEY_DSA_CERT: | ||
144 | if (k->dsa != NULL) | 194 | if (k->dsa != NULL) |
145 | DSA_free(k->dsa); | 195 | DSA_free(k->dsa); |
146 | k->dsa = NULL; | 196 | k->dsa = NULL; |
@@ -151,20 +201,49 @@ key_free(Key *k) | |||
151 | fatal("key_free: bad key type %d", k->type); | 201 | fatal("key_free: bad key type %d", k->type); |
152 | break; | 202 | break; |
153 | } | 203 | } |
204 | if (key_is_cert(k)) { | ||
205 | if (k->cert != NULL) | ||
206 | cert_free(k->cert); | ||
207 | k->cert = NULL; | ||
208 | } | ||
209 | |||
154 | xfree(k); | 210 | xfree(k); |
155 | } | 211 | } |
156 | 212 | ||
213 | static int | ||
214 | cert_compare(struct KeyCert *a, struct KeyCert *b) | ||
215 | { | ||
216 | if (a == NULL && b == NULL) | ||
217 | return 1; | ||
218 | if (a == NULL || b == NULL) | ||
219 | return 0; | ||
220 | if (buffer_len(&a->certblob) != buffer_len(&b->certblob)) | ||
221 | return 0; | ||
222 | if (memcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob), | ||
223 | buffer_len(&a->certblob)) != 0) | ||
224 | return 0; | ||
225 | return 1; | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * Compare public portions of key only, allowing comparisons between | ||
230 | * certificates and plain keys too. | ||
231 | */ | ||
157 | int | 232 | int |
158 | key_equal(const Key *a, const Key *b) | 233 | key_equal_public(const Key *a, const Key *b) |
159 | { | 234 | { |
160 | if (a == NULL || b == NULL || a->type != b->type) | 235 | if (a == NULL || b == NULL || |
236 | key_type_plain(a->type) != key_type_plain(b->type)) | ||
161 | return 0; | 237 | return 0; |
238 | |||
162 | switch (a->type) { | 239 | switch (a->type) { |
163 | case KEY_RSA1: | 240 | case KEY_RSA1: |
241 | case KEY_RSA_CERT: | ||
164 | case KEY_RSA: | 242 | case KEY_RSA: |
165 | return a->rsa != NULL && b->rsa != NULL && | 243 | return a->rsa != NULL && b->rsa != NULL && |
166 | BN_cmp(a->rsa->e, b->rsa->e) == 0 && | 244 | BN_cmp(a->rsa->e, b->rsa->e) == 0 && |
167 | BN_cmp(a->rsa->n, b->rsa->n) == 0; | 245 | BN_cmp(a->rsa->n, b->rsa->n) == 0; |
246 | case KEY_DSA_CERT: | ||
168 | case KEY_DSA: | 247 | case KEY_DSA: |
169 | return a->dsa != NULL && b->dsa != NULL && | 248 | return a->dsa != NULL && b->dsa != NULL && |
170 | BN_cmp(a->dsa->p, b->dsa->p) == 0 && | 249 | BN_cmp(a->dsa->p, b->dsa->p) == 0 && |
@@ -177,16 +256,27 @@ key_equal(const Key *a, const Key *b) | |||
177 | /* NOTREACHED */ | 256 | /* NOTREACHED */ |
178 | } | 257 | } |
179 | 258 | ||
259 | int | ||
260 | key_equal(const Key *a, const Key *b) | ||
261 | { | ||
262 | if (a == NULL || b == NULL || a->type != b->type) | ||
263 | return 0; | ||
264 | if (key_is_cert(a)) { | ||
265 | if (!cert_compare(a->cert, b->cert)) | ||
266 | return 0; | ||
267 | } | ||
268 | return key_equal_public(a, b); | ||
269 | } | ||
270 | |||
180 | u_char* | 271 | u_char* |
181 | key_fingerprint_raw(const Key *k, enum fp_type dgst_type, | 272 | key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length) |
182 | u_int *dgst_raw_length) | ||
183 | { | 273 | { |
184 | const EVP_MD *md = NULL; | 274 | const EVP_MD *md = NULL; |
185 | EVP_MD_CTX ctx; | 275 | EVP_MD_CTX ctx; |
186 | u_char *blob = NULL; | 276 | u_char *blob = NULL; |
187 | u_char *retval = NULL; | 277 | u_char *retval = NULL; |
188 | u_int len = 0; | 278 | u_int len = 0; |
189 | int nlen, elen; | 279 | int nlen, elen, otype; |
190 | 280 | ||
191 | *dgst_raw_length = 0; | 281 | *dgst_raw_length = 0; |
192 | 282 | ||
@@ -214,6 +304,14 @@ key_fingerprint_raw(const Key *k, enum fp_type dgst_type, | |||
214 | case KEY_RSA: | 304 | case KEY_RSA: |
215 | key_to_blob(k, &blob, &len); | 305 | key_to_blob(k, &blob, &len); |
216 | break; | 306 | break; |
307 | case KEY_DSA_CERT: | ||
308 | case KEY_RSA_CERT: | ||
309 | /* We want a fingerprint of the _key_ not of the cert */ | ||
310 | otype = k->type; | ||
311 | k->type = key_type_plain(k->type); | ||
312 | key_to_blob(k, &blob, &len); | ||
313 | k->type = otype; | ||
314 | break; | ||
217 | case KEY_UNSPEC: | 315 | case KEY_UNSPEC: |
218 | return retval; | 316 | return retval; |
219 | default: | 317 | default: |
@@ -408,7 +506,7 @@ key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k) | |||
408 | } | 506 | } |
409 | 507 | ||
410 | char * | 508 | char * |
411 | key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) | 509 | key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) |
412 | { | 510 | { |
413 | char *retval = NULL; | 511 | char *retval = NULL; |
414 | u_char *dgst_raw; | 512 | u_char *dgst_raw; |
@@ -533,6 +631,8 @@ key_read(Key *ret, char **cpp) | |||
533 | case KEY_UNSPEC: | 631 | case KEY_UNSPEC: |
534 | case KEY_RSA: | 632 | case KEY_RSA: |
535 | case KEY_DSA: | 633 | case KEY_DSA: |
634 | case KEY_DSA_CERT: | ||
635 | case KEY_RSA_CERT: | ||
536 | space = strchr(cp, ' '); | 636 | space = strchr(cp, ' '); |
537 | if (space == NULL) { | 637 | if (space == NULL) { |
538 | debug3("key_read: missing whitespace"); | 638 | debug3("key_read: missing whitespace"); |
@@ -577,25 +677,36 @@ key_read(Key *ret, char **cpp) | |||
577 | return -1; | 677 | return -1; |
578 | } | 678 | } |
579 | /*XXXX*/ | 679 | /*XXXX*/ |
580 | if (ret->type == KEY_RSA) { | 680 | if (key_is_cert(ret)) { |
681 | if (!key_is_cert(k)) { | ||
682 | error("key_read: loaded key is not a cert"); | ||
683 | key_free(k); | ||
684 | return -1; | ||
685 | } | ||
686 | if (ret->cert != NULL) | ||
687 | cert_free(ret->cert); | ||
688 | ret->cert = k->cert; | ||
689 | k->cert = NULL; | ||
690 | } | ||
691 | if (key_type_plain(ret->type) == KEY_RSA) { | ||
581 | if (ret->rsa != NULL) | 692 | if (ret->rsa != NULL) |
582 | RSA_free(ret->rsa); | 693 | RSA_free(ret->rsa); |
583 | ret->rsa = k->rsa; | 694 | ret->rsa = k->rsa; |
584 | k->rsa = NULL; | 695 | k->rsa = NULL; |
585 | success = 1; | ||
586 | #ifdef DEBUG_PK | 696 | #ifdef DEBUG_PK |
587 | RSA_print_fp(stderr, ret->rsa, 8); | 697 | RSA_print_fp(stderr, ret->rsa, 8); |
588 | #endif | 698 | #endif |
589 | } else { | 699 | } |
700 | if (key_type_plain(ret->type) == KEY_DSA) { | ||
590 | if (ret->dsa != NULL) | 701 | if (ret->dsa != NULL) |
591 | DSA_free(ret->dsa); | 702 | DSA_free(ret->dsa); |
592 | ret->dsa = k->dsa; | 703 | ret->dsa = k->dsa; |
593 | k->dsa = NULL; | 704 | k->dsa = NULL; |
594 | success = 1; | ||
595 | #ifdef DEBUG_PK | 705 | #ifdef DEBUG_PK |
596 | DSA_print_fp(stderr, ret->dsa, 8); | 706 | DSA_print_fp(stderr, ret->dsa, 8); |
597 | #endif | 707 | #endif |
598 | } | 708 | } |
709 | success = 1; | ||
599 | /*XXXX*/ | 710 | /*XXXX*/ |
600 | key_free(k); | 711 | key_free(k); |
601 | if (success != 1) | 712 | if (success != 1) |
@@ -622,28 +733,53 @@ key_write(const Key *key, FILE *f) | |||
622 | u_char *blob; | 733 | u_char *blob; |
623 | char *uu; | 734 | char *uu; |
624 | 735 | ||
625 | if (key->type == KEY_RSA1 && key->rsa != NULL) { | 736 | if (key_is_cert(key)) { |
737 | if (key->cert == NULL) { | ||
738 | error("%s: no cert data", __func__); | ||
739 | return 0; | ||
740 | } | ||
741 | if (buffer_len(&key->cert->certblob) == 0) { | ||
742 | error("%s: no signed certificate blob", __func__); | ||
743 | return 0; | ||
744 | } | ||
745 | } | ||
746 | |||
747 | switch (key->type) { | ||
748 | case KEY_RSA1: | ||
749 | if (key->rsa == NULL) | ||
750 | return 0; | ||
626 | /* size of modulus 'n' */ | 751 | /* size of modulus 'n' */ |
627 | bits = BN_num_bits(key->rsa->n); | 752 | bits = BN_num_bits(key->rsa->n); |
628 | fprintf(f, "%u", bits); | 753 | fprintf(f, "%u", bits); |
629 | if (write_bignum(f, key->rsa->e) && | 754 | if (write_bignum(f, key->rsa->e) && |
630 | write_bignum(f, key->rsa->n)) { | 755 | write_bignum(f, key->rsa->n)) |
631 | success = 1; | 756 | return 1; |
632 | } else { | 757 | error("key_write: failed for RSA key"); |
633 | error("key_write: failed for RSA key"); | 758 | return 0; |
634 | } | 759 | case KEY_DSA: |
635 | } else if ((key->type == KEY_DSA && key->dsa != NULL) || | 760 | case KEY_DSA_CERT: |
636 | (key->type == KEY_RSA && key->rsa != NULL)) { | 761 | if (key->dsa == NULL) |
637 | key_to_blob(key, &blob, &len); | 762 | return 0; |
638 | uu = xmalloc(2*len); | 763 | break; |
639 | n = uuencode(blob, len, uu, 2*len); | 764 | case KEY_RSA: |
640 | if (n > 0) { | 765 | case KEY_RSA_CERT: |
641 | fprintf(f, "%s %s", key_ssh_name(key), uu); | 766 | if (key->rsa == NULL) |
642 | success = 1; | 767 | return 0; |
643 | } | 768 | break; |
644 | xfree(blob); | 769 | default: |
645 | xfree(uu); | 770 | return 0; |
646 | } | 771 | } |
772 | |||
773 | key_to_blob(key, &blob, &len); | ||
774 | uu = xmalloc(2*len); | ||
775 | n = uuencode(blob, len, uu, 2*len); | ||
776 | if (n > 0) { | ||
777 | fprintf(f, "%s %s", key_ssh_name(key), uu); | ||
778 | success = 1; | ||
779 | } | ||
780 | xfree(blob); | ||
781 | xfree(uu); | ||
782 | |||
647 | return success; | 783 | return success; |
648 | } | 784 | } |
649 | 785 | ||
@@ -657,6 +793,10 @@ key_type(const Key *k) | |||
657 | return "RSA"; | 793 | return "RSA"; |
658 | case KEY_DSA: | 794 | case KEY_DSA: |
659 | return "DSA"; | 795 | return "DSA"; |
796 | case KEY_RSA_CERT: | ||
797 | return "RSA-CERT"; | ||
798 | case KEY_DSA_CERT: | ||
799 | return "DSA-CERT"; | ||
660 | } | 800 | } |
661 | return "unknown"; | 801 | return "unknown"; |
662 | } | 802 | } |
@@ -669,6 +809,10 @@ key_ssh_name(const Key *k) | |||
669 | return "ssh-rsa"; | 809 | return "ssh-rsa"; |
670 | case KEY_DSA: | 810 | case KEY_DSA: |
671 | return "ssh-dss"; | 811 | return "ssh-dss"; |
812 | case KEY_RSA_CERT: | ||
813 | return "ssh-rsa-cert-v00@openssh.com"; | ||
814 | case KEY_DSA_CERT: | ||
815 | return "ssh-dss-cert-v00@openssh.com"; | ||
672 | } | 816 | } |
673 | return "ssh-unknown"; | 817 | return "ssh-unknown"; |
674 | } | 818 | } |
@@ -679,8 +823,10 @@ key_size(const Key *k) | |||
679 | switch (k->type) { | 823 | switch (k->type) { |
680 | case KEY_RSA1: | 824 | case KEY_RSA1: |
681 | case KEY_RSA: | 825 | case KEY_RSA: |
826 | case KEY_RSA_CERT: | ||
682 | return BN_num_bits(k->rsa->n); | 827 | return BN_num_bits(k->rsa->n); |
683 | case KEY_DSA: | 828 | case KEY_DSA: |
829 | case KEY_DSA_CERT: | ||
684 | return BN_num_bits(k->dsa->p); | 830 | return BN_num_bits(k->dsa->p); |
685 | } | 831 | } |
686 | return 0; | 832 | return 0; |
@@ -723,6 +869,9 @@ key_generate(int type, u_int bits) | |||
723 | case KEY_RSA1: | 869 | case KEY_RSA1: |
724 | k->rsa = rsa_generate_private_key(bits); | 870 | k->rsa = rsa_generate_private_key(bits); |
725 | break; | 871 | break; |
872 | case KEY_RSA_CERT: | ||
873 | case KEY_DSA_CERT: | ||
874 | fatal("key_generate: cert keys cannot be generated directly"); | ||
726 | default: | 875 | default: |
727 | fatal("key_generate: unknown type %d", type); | 876 | fatal("key_generate: unknown type %d", type); |
728 | } | 877 | } |
@@ -730,12 +879,55 @@ key_generate(int type, u_int bits) | |||
730 | return k; | 879 | return k; |
731 | } | 880 | } |
732 | 881 | ||
882 | void | ||
883 | key_cert_copy(const Key *from_key, struct Key *to_key) | ||
884 | { | ||
885 | u_int i; | ||
886 | const struct KeyCert *from; | ||
887 | struct KeyCert *to; | ||
888 | |||
889 | if (to_key->cert != NULL) { | ||
890 | cert_free(to_key->cert); | ||
891 | to_key->cert = NULL; | ||
892 | } | ||
893 | |||
894 | if ((from = from_key->cert) == NULL) | ||
895 | return; | ||
896 | |||
897 | to = to_key->cert = cert_new(); | ||
898 | |||
899 | buffer_append(&to->certblob, buffer_ptr(&from->certblob), | ||
900 | buffer_len(&from->certblob)); | ||
901 | |||
902 | buffer_append(&to->constraints, buffer_ptr(&from->constraints), | ||
903 | buffer_len(&from->constraints)); | ||
904 | |||
905 | to->type = from->type; | ||
906 | to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id); | ||
907 | to->valid_after = from->valid_after; | ||
908 | to->valid_before = from->valid_before; | ||
909 | to->signature_key = from->signature_key == NULL ? | ||
910 | NULL : key_from_private(from->signature_key); | ||
911 | |||
912 | to->nprincipals = from->nprincipals; | ||
913 | if (to->nprincipals > CERT_MAX_PRINCIPALS) | ||
914 | fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)", | ||
915 | __func__, to->nprincipals, CERT_MAX_PRINCIPALS); | ||
916 | if (to->nprincipals > 0) { | ||
917 | to->principals = xcalloc(from->nprincipals, | ||
918 | sizeof(*to->principals)); | ||
919 | for (i = 0; i < to->nprincipals; i++) | ||
920 | to->principals[i] = xstrdup(from->principals[i]); | ||
921 | } | ||
922 | } | ||
923 | |||
733 | Key * | 924 | Key * |
734 | key_from_private(const Key *k) | 925 | key_from_private(const Key *k) |
735 | { | 926 | { |
736 | Key *n = NULL; | 927 | Key *n = NULL; |
737 | switch (k->type) { | 928 | switch (k->type) { |
738 | case KEY_DSA: | 929 | case KEY_DSA: |
930 | case KEY_DSA_CERT: | ||
739 | n = key_new(k->type); | 931 | n = key_new(k->type); |
740 | if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) || | 932 | if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) || |
741 | (BN_copy(n->dsa->q, k->dsa->q) == NULL) || | 933 | (BN_copy(n->dsa->q, k->dsa->q) == NULL) || |
@@ -745,6 +937,7 @@ key_from_private(const Key *k) | |||
745 | break; | 937 | break; |
746 | case KEY_RSA: | 938 | case KEY_RSA: |
747 | case KEY_RSA1: | 939 | case KEY_RSA1: |
940 | case KEY_RSA_CERT: | ||
748 | n = key_new(k->type); | 941 | n = key_new(k->type); |
749 | if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) || | 942 | if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) || |
750 | (BN_copy(n->rsa->e, k->rsa->e) == NULL)) | 943 | (BN_copy(n->rsa->e, k->rsa->e) == NULL)) |
@@ -754,6 +947,8 @@ key_from_private(const Key *k) | |||
754 | fatal("key_from_private: unknown type %d", k->type); | 947 | fatal("key_from_private: unknown type %d", k->type); |
755 | break; | 948 | break; |
756 | } | 949 | } |
950 | if (key_is_cert(k)) | ||
951 | key_cert_copy(k, n); | ||
757 | return n; | 952 | return n; |
758 | } | 953 | } |
759 | 954 | ||
@@ -770,6 +965,10 @@ key_type_from_name(char *name) | |||
770 | return KEY_RSA; | 965 | return KEY_RSA; |
771 | } else if (strcmp(name, "ssh-dss") == 0) { | 966 | } else if (strcmp(name, "ssh-dss") == 0) { |
772 | return KEY_DSA; | 967 | return KEY_DSA; |
968 | } else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) { | ||
969 | return KEY_RSA_CERT; | ||
970 | } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) { | ||
971 | return KEY_DSA_CERT; | ||
773 | } | 972 | } |
774 | debug2("key_type_from_name: unknown key type '%s'", name); | 973 | debug2("key_type_from_name: unknown key type '%s'", name); |
775 | return KEY_UNSPEC; | 974 | return KEY_UNSPEC; |
@@ -797,6 +996,117 @@ key_names_valid2(const char *names) | |||
797 | return 1; | 996 | return 1; |
798 | } | 997 | } |
799 | 998 | ||
999 | static int | ||
1000 | cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) | ||
1001 | { | ||
1002 | u_char *principals, *constraints, *sig_key, *sig; | ||
1003 | u_int signed_len, plen, clen, sklen, slen; | ||
1004 | Buffer tmp; | ||
1005 | char *principal; | ||
1006 | int ret = -1; | ||
1007 | |||
1008 | buffer_init(&tmp); | ||
1009 | |||
1010 | /* Copy the entire key blob for verification and later serialisation */ | ||
1011 | buffer_append(&key->cert->certblob, blob, blen); | ||
1012 | |||
1013 | principals = constraints = sig_key = sig = NULL; | ||
1014 | if (buffer_get_int_ret(&key->cert->type, b) != 0 || | ||
1015 | (key->cert->key_id = buffer_get_string_ret(b, NULL)) == NULL || | ||
1016 | (principals = buffer_get_string_ret(b, &plen)) == NULL || | ||
1017 | buffer_get_int64_ret(&key->cert->valid_after, b) != 0 || | ||
1018 | buffer_get_int64_ret(&key->cert->valid_before, b) != 0 || | ||
1019 | (constraints = buffer_get_string_ret(b, &clen)) == NULL || | ||
1020 | /* skip nonce */ buffer_get_string_ptr_ret(b, NULL) == NULL || | ||
1021 | /* skip reserved */ buffer_get_string_ptr_ret(b, NULL) == NULL || | ||
1022 | (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) { | ||
1023 | error("%s: parse error", __func__); | ||
1024 | goto out; | ||
1025 | } | ||
1026 | |||
1027 | /* Signature is left in the buffer so we can calculate this length */ | ||
1028 | signed_len = buffer_len(&key->cert->certblob) - buffer_len(b); | ||
1029 | |||
1030 | if ((sig = buffer_get_string_ret(b, &slen)) == NULL) { | ||
1031 | error("%s: parse error", __func__); | ||
1032 | goto out; | ||
1033 | } | ||
1034 | |||
1035 | if (key->cert->type != SSH2_CERT_TYPE_USER && | ||
1036 | key->cert->type != SSH2_CERT_TYPE_HOST) { | ||
1037 | error("Unknown certificate type %u", key->cert->type); | ||
1038 | goto out; | ||
1039 | } | ||
1040 | |||
1041 | buffer_append(&tmp, principals, plen); | ||
1042 | while (buffer_len(&tmp) > 0) { | ||
1043 | if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) { | ||
1044 | error("Too many principals"); | ||
1045 | goto out; | ||
1046 | } | ||
1047 | if ((principal = buffer_get_string_ret(&tmp, NULL)) == NULL) { | ||
1048 | error("Principals data invalid"); | ||
1049 | goto out; | ||
1050 | } | ||
1051 | key->cert->principals = xrealloc(key->cert->principals, | ||
1052 | key->cert->nprincipals + 1, sizeof(*key->cert->principals)); | ||
1053 | key->cert->principals[key->cert->nprincipals++] = principal; | ||
1054 | } | ||
1055 | |||
1056 | buffer_clear(&tmp); | ||
1057 | |||
1058 | buffer_append(&key->cert->constraints, constraints, clen); | ||
1059 | buffer_append(&tmp, constraints, clen); | ||
1060 | /* validate structure */ | ||
1061 | while (buffer_len(&tmp) != 0) { | ||
1062 | if (buffer_get_string_ptr(&tmp, NULL) == NULL || | ||
1063 | buffer_get_string_ptr(&tmp, NULL) == NULL) { | ||
1064 | error("Constraints data invalid"); | ||
1065 | goto out; | ||
1066 | } | ||
1067 | } | ||
1068 | buffer_clear(&tmp); | ||
1069 | |||
1070 | if ((key->cert->signature_key = key_from_blob(sig_key, | ||
1071 | sklen)) == NULL) { | ||
1072 | error("Signature key invalid"); | ||
1073 | goto out; | ||
1074 | } | ||
1075 | if (key->cert->signature_key->type != KEY_RSA && | ||
1076 | key->cert->signature_key->type != KEY_DSA) { | ||
1077 | error("Invalid signature key type %s (%d)", | ||
1078 | key_type(key->cert->signature_key), | ||
1079 | key->cert->signature_key->type); | ||
1080 | goto out; | ||
1081 | } | ||
1082 | |||
1083 | switch (key_verify(key->cert->signature_key, sig, slen, | ||
1084 | buffer_ptr(&key->cert->certblob), signed_len)) { | ||
1085 | case 1: | ||
1086 | break; /* Good signature */ | ||
1087 | case 0: | ||
1088 | error("Invalid signature on certificate"); | ||
1089 | goto out; | ||
1090 | case -1: | ||
1091 | error("Certificate signature verification failed"); | ||
1092 | goto out; | ||
1093 | } | ||
1094 | |||
1095 | ret = 0; | ||
1096 | |||
1097 | out: | ||
1098 | buffer_free(&tmp); | ||
1099 | if (principals != NULL) | ||
1100 | xfree(principals); | ||
1101 | if (constraints != NULL) | ||
1102 | xfree(constraints); | ||
1103 | if (sig_key != NULL) | ||
1104 | xfree(sig_key); | ||
1105 | if (sig != NULL) | ||
1106 | xfree(sig); | ||
1107 | return ret; | ||
1108 | } | ||
1109 | |||
800 | Key * | 1110 | Key * |
801 | key_from_blob(const u_char *blob, u_int blen) | 1111 | key_from_blob(const u_char *blob, u_int blen) |
802 | { | 1112 | { |
@@ -819,10 +1129,12 @@ key_from_blob(const u_char *blob, u_int blen) | |||
819 | 1129 | ||
820 | switch (type) { | 1130 | switch (type) { |
821 | case KEY_RSA: | 1131 | case KEY_RSA: |
1132 | case KEY_RSA_CERT: | ||
822 | key = key_new(type); | 1133 | key = key_new(type); |
823 | if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 || | 1134 | if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 || |
824 | buffer_get_bignum2_ret(&b, key->rsa->n) == -1) { | 1135 | buffer_get_bignum2_ret(&b, key->rsa->n) == -1) { |
825 | error("key_from_blob: can't read rsa key"); | 1136 | error("key_from_blob: can't read rsa key"); |
1137 | badkey: | ||
826 | key_free(key); | 1138 | key_free(key); |
827 | key = NULL; | 1139 | key = NULL; |
828 | goto out; | 1140 | goto out; |
@@ -832,15 +1144,14 @@ key_from_blob(const u_char *blob, u_int blen) | |||
832 | #endif | 1144 | #endif |
833 | break; | 1145 | break; |
834 | case KEY_DSA: | 1146 | case KEY_DSA: |
1147 | case KEY_DSA_CERT: | ||
835 | key = key_new(type); | 1148 | key = key_new(type); |
836 | if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 || | 1149 | if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 || |
837 | buffer_get_bignum2_ret(&b, key->dsa->q) == -1 || | 1150 | buffer_get_bignum2_ret(&b, key->dsa->q) == -1 || |
838 | buffer_get_bignum2_ret(&b, key->dsa->g) == -1 || | 1151 | buffer_get_bignum2_ret(&b, key->dsa->g) == -1 || |
839 | buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) { | 1152 | buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) { |
840 | error("key_from_blob: can't read dsa key"); | 1153 | error("key_from_blob: can't read dsa key"); |
841 | key_free(key); | 1154 | goto badkey; |
842 | key = NULL; | ||
843 | goto out; | ||
844 | } | 1155 | } |
845 | #ifdef DEBUG_PK | 1156 | #ifdef DEBUG_PK |
846 | DSA_print_fp(stderr, key->dsa, 8); | 1157 | DSA_print_fp(stderr, key->dsa, 8); |
@@ -853,6 +1164,10 @@ key_from_blob(const u_char *blob, u_int blen) | |||
853 | error("key_from_blob: cannot handle type %s", ktype); | 1164 | error("key_from_blob: cannot handle type %s", ktype); |
854 | goto out; | 1165 | goto out; |
855 | } | 1166 | } |
1167 | if (key_is_cert(key) && cert_parse(&b, key, blob, blen) == -1) { | ||
1168 | error("key_from_blob: can't parse cert data"); | ||
1169 | goto badkey; | ||
1170 | } | ||
856 | rlen = buffer_len(&b); | 1171 | rlen = buffer_len(&b); |
857 | if (key != NULL && rlen != 0) | 1172 | if (key != NULL && rlen != 0) |
858 | error("key_from_blob: remaining bytes in key blob %d", rlen); | 1173 | error("key_from_blob: remaining bytes in key blob %d", rlen); |
@@ -875,6 +1190,12 @@ key_to_blob(const Key *key, u_char **blobp, u_int *lenp) | |||
875 | } | 1190 | } |
876 | buffer_init(&b); | 1191 | buffer_init(&b); |
877 | switch (key->type) { | 1192 | switch (key->type) { |
1193 | case KEY_DSA_CERT: | ||
1194 | case KEY_RSA_CERT: | ||
1195 | /* Use the existing blob */ | ||
1196 | buffer_append(&b, buffer_ptr(&key->cert->certblob), | ||
1197 | buffer_len(&key->cert->certblob)); | ||
1198 | break; | ||
878 | case KEY_DSA: | 1199 | case KEY_DSA: |
879 | buffer_put_cstring(&b, key_ssh_name(key)); | 1200 | buffer_put_cstring(&b, key_ssh_name(key)); |
880 | buffer_put_bignum2(&b, key->dsa->p); | 1201 | buffer_put_bignum2(&b, key->dsa->p); |
@@ -911,8 +1232,10 @@ key_sign( | |||
911 | const u_char *data, u_int datalen) | 1232 | const u_char *data, u_int datalen) |
912 | { | 1233 | { |
913 | switch (key->type) { | 1234 | switch (key->type) { |
1235 | case KEY_DSA_CERT: | ||
914 | case KEY_DSA: | 1236 | case KEY_DSA: |
915 | return ssh_dss_sign(key, sigp, lenp, data, datalen); | 1237 | return ssh_dss_sign(key, sigp, lenp, data, datalen); |
1238 | case KEY_RSA_CERT: | ||
916 | case KEY_RSA: | 1239 | case KEY_RSA: |
917 | return ssh_rsa_sign(key, sigp, lenp, data, datalen); | 1240 | return ssh_rsa_sign(key, sigp, lenp, data, datalen); |
918 | default: | 1241 | default: |
@@ -935,8 +1258,10 @@ key_verify( | |||
935 | return -1; | 1258 | return -1; |
936 | 1259 | ||
937 | switch (key->type) { | 1260 | switch (key->type) { |
1261 | case KEY_DSA_CERT: | ||
938 | case KEY_DSA: | 1262 | case KEY_DSA: |
939 | return ssh_dss_verify(key, signature, signaturelen, data, datalen); | 1263 | return ssh_dss_verify(key, signature, signaturelen, data, datalen); |
1264 | case KEY_RSA_CERT: | ||
940 | case KEY_RSA: | 1265 | case KEY_RSA: |
941 | return ssh_rsa_verify(key, signature, signaturelen, data, datalen); | 1266 | return ssh_rsa_verify(key, signature, signaturelen, data, datalen); |
942 | default: | 1267 | default: |
@@ -958,6 +1283,9 @@ key_demote(const Key *k) | |||
958 | pk->rsa = NULL; | 1283 | pk->rsa = NULL; |
959 | 1284 | ||
960 | switch (k->type) { | 1285 | switch (k->type) { |
1286 | case KEY_RSA_CERT: | ||
1287 | key_cert_copy(k, pk); | ||
1288 | /* FALLTHROUGH */ | ||
961 | case KEY_RSA1: | 1289 | case KEY_RSA1: |
962 | case KEY_RSA: | 1290 | case KEY_RSA: |
963 | if ((pk->rsa = RSA_new()) == NULL) | 1291 | if ((pk->rsa = RSA_new()) == NULL) |
@@ -967,6 +1295,9 @@ key_demote(const Key *k) | |||
967 | if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL) | 1295 | if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL) |
968 | fatal("key_demote: BN_dup failed"); | 1296 | fatal("key_demote: BN_dup failed"); |
969 | break; | 1297 | break; |
1298 | case KEY_DSA_CERT: | ||
1299 | key_cert_copy(k, pk); | ||
1300 | /* FALLTHROUGH */ | ||
970 | case KEY_DSA: | 1301 | case KEY_DSA: |
971 | if ((pk->dsa = DSA_new()) == NULL) | 1302 | if ((pk->dsa = DSA_new()) == NULL) |
972 | fatal("key_demote: DSA_new failed"); | 1303 | fatal("key_demote: DSA_new failed"); |
@@ -986,3 +1317,199 @@ key_demote(const Key *k) | |||
986 | 1317 | ||
987 | return (pk); | 1318 | return (pk); |
988 | } | 1319 | } |
1320 | |||
1321 | int | ||
1322 | key_is_cert(const Key *k) | ||
1323 | { | ||
1324 | return k != NULL && | ||
1325 | (k->type == KEY_RSA_CERT || k->type == KEY_DSA_CERT); | ||
1326 | } | ||
1327 | |||
1328 | /* Return the cert-less equivalent to a certified key type */ | ||
1329 | int | ||
1330 | key_type_plain(int type) | ||
1331 | { | ||
1332 | switch (type) { | ||
1333 | case KEY_RSA_CERT: | ||
1334 | return KEY_RSA; | ||
1335 | case KEY_DSA_CERT: | ||
1336 | return KEY_DSA; | ||
1337 | default: | ||
1338 | return type; | ||
1339 | } | ||
1340 | } | ||
1341 | |||
1342 | /* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */ | ||
1343 | int | ||
1344 | key_to_certified(Key *k) | ||
1345 | { | ||
1346 | switch (k->type) { | ||
1347 | case KEY_RSA: | ||
1348 | k->cert = cert_new(); | ||
1349 | k->type = KEY_RSA_CERT; | ||
1350 | return 0; | ||
1351 | case KEY_DSA: | ||
1352 | k->cert = cert_new(); | ||
1353 | k->type = KEY_DSA_CERT; | ||
1354 | return 0; | ||
1355 | default: | ||
1356 | error("%s: key has incorrect type %s", __func__, key_type(k)); | ||
1357 | return -1; | ||
1358 | } | ||
1359 | } | ||
1360 | |||
1361 | /* Convert a KEY_RSA_CERT or KEY_DSA_CERT to their raw key equivalent */ | ||
1362 | int | ||
1363 | key_drop_cert(Key *k) | ||
1364 | { | ||
1365 | switch (k->type) { | ||
1366 | case KEY_RSA_CERT: | ||
1367 | cert_free(k->cert); | ||
1368 | k->type = KEY_RSA; | ||
1369 | return 0; | ||
1370 | case KEY_DSA_CERT: | ||
1371 | cert_free(k->cert); | ||
1372 | k->type = KEY_DSA; | ||
1373 | return 0; | ||
1374 | default: | ||
1375 | error("%s: key has incorrect type %s", __func__, key_type(k)); | ||
1376 | return -1; | ||
1377 | } | ||
1378 | } | ||
1379 | |||
1380 | /* Sign a KEY_RSA_CERT or KEY_DSA_CERT, (re-)generating the signed certblob */ | ||
1381 | int | ||
1382 | key_certify(Key *k, Key *ca) | ||
1383 | { | ||
1384 | Buffer principals; | ||
1385 | u_char *ca_blob, *sig_blob, nonce[32]; | ||
1386 | u_int i, ca_len, sig_len; | ||
1387 | |||
1388 | if (k->cert == NULL) { | ||
1389 | error("%s: key lacks cert info", __func__); | ||
1390 | return -1; | ||
1391 | } | ||
1392 | |||
1393 | if (!key_is_cert(k)) { | ||
1394 | error("%s: certificate has unknown type %d", __func__, | ||
1395 | k->cert->type); | ||
1396 | return -1; | ||
1397 | } | ||
1398 | |||
1399 | if (ca->type != KEY_RSA && ca->type != KEY_DSA) { | ||
1400 | error("%s: CA key has unsupported type %s", __func__, | ||
1401 | key_type(ca)); | ||
1402 | return -1; | ||
1403 | } | ||
1404 | |||
1405 | key_to_blob(ca, &ca_blob, &ca_len); | ||
1406 | |||
1407 | buffer_clear(&k->cert->certblob); | ||
1408 | buffer_put_cstring(&k->cert->certblob, key_ssh_name(k)); | ||
1409 | |||
1410 | switch (k->type) { | ||
1411 | case KEY_DSA_CERT: | ||
1412 | buffer_put_bignum2(&k->cert->certblob, k->dsa->p); | ||
1413 | buffer_put_bignum2(&k->cert->certblob, k->dsa->q); | ||
1414 | buffer_put_bignum2(&k->cert->certblob, k->dsa->g); | ||
1415 | buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key); | ||
1416 | break; | ||
1417 | case KEY_RSA_CERT: | ||
1418 | buffer_put_bignum2(&k->cert->certblob, k->rsa->e); | ||
1419 | buffer_put_bignum2(&k->cert->certblob, k->rsa->n); | ||
1420 | break; | ||
1421 | default: | ||
1422 | error("%s: key has incorrect type %s", __func__, key_type(k)); | ||
1423 | buffer_clear(&k->cert->certblob); | ||
1424 | xfree(ca_blob); | ||
1425 | return -1; | ||
1426 | } | ||
1427 | |||
1428 | buffer_put_int(&k->cert->certblob, k->cert->type); | ||
1429 | buffer_put_cstring(&k->cert->certblob, k->cert->key_id); | ||
1430 | |||
1431 | buffer_init(&principals); | ||
1432 | for (i = 0; i < k->cert->nprincipals; i++) | ||
1433 | buffer_put_cstring(&principals, k->cert->principals[i]); | ||
1434 | buffer_put_string(&k->cert->certblob, buffer_ptr(&principals), | ||
1435 | buffer_len(&principals)); | ||
1436 | buffer_free(&principals); | ||
1437 | |||
1438 | buffer_put_int64(&k->cert->certblob, k->cert->valid_after); | ||
1439 | buffer_put_int64(&k->cert->certblob, k->cert->valid_before); | ||
1440 | buffer_put_string(&k->cert->certblob, | ||
1441 | buffer_ptr(&k->cert->constraints), | ||
1442 | buffer_len(&k->cert->constraints)); | ||
1443 | |||
1444 | arc4random_buf(&nonce, sizeof(nonce)); | ||
1445 | buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); | ||
1446 | buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */ | ||
1447 | buffer_put_string(&k->cert->certblob, ca_blob, ca_len); | ||
1448 | xfree(ca_blob); | ||
1449 | |||
1450 | /* Sign the whole mess */ | ||
1451 | if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob), | ||
1452 | buffer_len(&k->cert->certblob)) != 0) { | ||
1453 | error("%s: signature operation failed", __func__); | ||
1454 | buffer_clear(&k->cert->certblob); | ||
1455 | return -1; | ||
1456 | } | ||
1457 | /* Append signature and we are done */ | ||
1458 | buffer_put_string(&k->cert->certblob, sig_blob, sig_len); | ||
1459 | xfree(sig_blob); | ||
1460 | |||
1461 | return 0; | ||
1462 | } | ||
1463 | |||
1464 | int | ||
1465 | key_cert_check_authority(const Key *k, int want_host, int require_principal, | ||
1466 | const char *name, const char **reason) | ||
1467 | { | ||
1468 | u_int i, principal_matches; | ||
1469 | time_t now = time(NULL); | ||
1470 | |||
1471 | if (want_host) { | ||
1472 | if (k->cert->type != SSH2_CERT_TYPE_HOST) { | ||
1473 | *reason = "Certificate invalid: not a host certificate"; | ||
1474 | return -1; | ||
1475 | } | ||
1476 | } else { | ||
1477 | if (k->cert->type != SSH2_CERT_TYPE_USER) { | ||
1478 | *reason = "Certificate invalid: not a user certificate"; | ||
1479 | return -1; | ||
1480 | } | ||
1481 | } | ||
1482 | if (now < 0) { | ||
1483 | error("%s: system clock lies before epoch", __func__); | ||
1484 | *reason = "Certificate invalid: not yet valid"; | ||
1485 | return -1; | ||
1486 | } | ||
1487 | if ((u_int64_t)now < k->cert->valid_after) { | ||
1488 | *reason = "Certificate invalid: not yet valid"; | ||
1489 | return -1; | ||
1490 | } | ||
1491 | if ((u_int64_t)now >= k->cert->valid_before) { | ||
1492 | *reason = "Certificate invalid: expired"; | ||
1493 | return -1; | ||
1494 | } | ||
1495 | if (k->cert->nprincipals == 0) { | ||
1496 | if (require_principal) { | ||
1497 | *reason = "Certificate lacks principal list"; | ||
1498 | return -1; | ||
1499 | } | ||
1500 | } else { | ||
1501 | principal_matches = 0; | ||
1502 | for (i = 0; i < k->cert->nprincipals; i++) { | ||
1503 | if (strcmp(name, k->cert->principals[i]) == 0) { | ||
1504 | principal_matches = 1; | ||
1505 | break; | ||
1506 | } | ||
1507 | } | ||
1508 | if (!principal_matches) { | ||
1509 | *reason = "Certificate invalid: name is not a listed " | ||
1510 | "principal"; | ||
1511 | return -1; | ||
1512 | } | ||
1513 | } | ||
1514 | return 0; | ||
1515 | } | ||