diff options
author | Colin Watson <cjwatson@debian.org> | 2015-08-19 14:23:51 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2015-08-19 16:48:11 +0100 |
commit | 0f0841b2d28b7463267d4d91577e72e3340a1d3a (patch) | |
tree | ba55fcd2b6e2cc22b30f5afb561dbb3da4c8b6c7 /sshkey.c | |
parent | f2a5f5dae656759efb0b76c3d94890b65c197a02 (diff) | |
parent | 8698446b972003b63dfe5dcbdb86acfe986afb85 (diff) |
New upstream release (6.8p1).
Diffstat (limited to 'sshkey.c')
-rw-r--r-- | sshkey.c | 415 |
1 files changed, 250 insertions, 165 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.c,v 1.3 2014/07/03 01:45:38 djm Exp $ */ | 1 | /* $OpenBSD: sshkey.c,v 1.15 2015/03/06 01:40:56 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. | 4 | * Copyright (c) 2008 Alexander von Gernler. All rights reserved. |
@@ -27,18 +27,23 @@ | |||
27 | 27 | ||
28 | #include "includes.h" | 28 | #include "includes.h" |
29 | 29 | ||
30 | #include <sys/param.h> | 30 | #include <sys/param.h> /* MIN MAX */ |
31 | #include <sys/types.h> | 31 | #include <sys/types.h> |
32 | #include <netinet/in.h> | ||
32 | 33 | ||
34 | #ifdef WITH_OPENSSL | ||
33 | #include <openssl/evp.h> | 35 | #include <openssl/evp.h> |
34 | #include <openssl/err.h> | 36 | #include <openssl/err.h> |
35 | #include <openssl/pem.h> | 37 | #include <openssl/pem.h> |
38 | #endif | ||
36 | 39 | ||
37 | #include "crypto_api.h" | 40 | #include "crypto_api.h" |
38 | 41 | ||
39 | #include <errno.h> | 42 | #include <errno.h> |
43 | #include <limits.h> | ||
40 | #include <stdio.h> | 44 | #include <stdio.h> |
41 | #include <string.h> | 45 | #include <string.h> |
46 | #include <resolv.h> | ||
42 | #ifdef HAVE_UTIL_H | 47 | #ifdef HAVE_UTIL_H |
43 | #include <util.h> | 48 | #include <util.h> |
44 | #endif /* HAVE_UTIL_H */ | 49 | #endif /* HAVE_UTIL_H */ |
@@ -52,6 +57,7 @@ | |||
52 | #include "digest.h" | 57 | #include "digest.h" |
53 | #define SSHKEY_INTERNAL | 58 | #define SSHKEY_INTERNAL |
54 | #include "sshkey.h" | 59 | #include "sshkey.h" |
60 | #include "match.h" | ||
55 | 61 | ||
56 | /* openssh private key file format */ | 62 | /* openssh private key file format */ |
57 | #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" | 63 | #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" |
@@ -67,7 +73,7 @@ | |||
67 | /* Version identification string for SSH v1 identity files. */ | 73 | /* Version identification string for SSH v1 identity files. */ |
68 | #define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n" | 74 | #define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n" |
69 | 75 | ||
70 | static int sshkey_from_blob_internal(const u_char *blob, size_t blen, | 76 | static int sshkey_from_blob_internal(struct sshbuf *buf, |
71 | struct sshkey **keyp, int allow_cert); | 77 | struct sshkey **keyp, int allow_cert); |
72 | 78 | ||
73 | /* Supported key types */ | 79 | /* Supported key types */ |
@@ -182,12 +188,12 @@ sshkey_ecdsa_nid_from_name(const char *name) | |||
182 | { | 188 | { |
183 | const struct keytype *kt; | 189 | const struct keytype *kt; |
184 | 190 | ||
185 | for (kt = keytypes; kt->type != -1; kt++) { | 191 | for (kt = keytypes; kt->type != -1; kt++) { |
186 | if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) | 192 | if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) |
187 | continue; | 193 | continue; |
188 | if (kt->name != NULL && strcmp(name, kt->name) == 0) | 194 | if (kt->name != NULL && strcmp(name, kt->name) == 0) |
189 | return kt->nid; | 195 | return kt->nid; |
190 | } | 196 | } |
191 | return -1; | 197 | return -1; |
192 | } | 198 | } |
193 | 199 | ||
@@ -218,9 +224,11 @@ key_alg_list(int certs_only, int plain_only) | |||
218 | } | 224 | } |
219 | 225 | ||
220 | int | 226 | int |
221 | sshkey_names_valid2(const char *names) | 227 | sshkey_names_valid2(const char *names, int allow_wildcard) |
222 | { | 228 | { |
223 | char *s, *cp, *p; | 229 | char *s, *cp, *p; |
230 | const struct keytype *kt; | ||
231 | int type; | ||
224 | 232 | ||
225 | if (names == NULL || strcmp(names, "") == 0) | 233 | if (names == NULL || strcmp(names, "") == 0) |
226 | return 0; | 234 | return 0; |
@@ -228,9 +236,28 @@ sshkey_names_valid2(const char *names) | |||
228 | return 0; | 236 | return 0; |
229 | for ((p = strsep(&cp, ",")); p && *p != '\0'; | 237 | for ((p = strsep(&cp, ",")); p && *p != '\0'; |
230 | (p = strsep(&cp, ","))) { | 238 | (p = strsep(&cp, ","))) { |
231 | switch (sshkey_type_from_name(p)) { | 239 | type = sshkey_type_from_name(p); |
232 | case KEY_RSA1: | 240 | if (type == KEY_RSA1) { |
233 | case KEY_UNSPEC: | 241 | free(s); |
242 | return 0; | ||
243 | } | ||
244 | if (type == KEY_UNSPEC) { | ||
245 | if (allow_wildcard) { | ||
246 | /* | ||
247 | * Try matching key types against the string. | ||
248 | * If any has a positive or negative match then | ||
249 | * the component is accepted. | ||
250 | */ | ||
251 | for (kt = keytypes; kt->type != -1; kt++) { | ||
252 | if (kt->type == KEY_RSA1) | ||
253 | continue; | ||
254 | if (match_pattern_list(kt->name, | ||
255 | p, strlen(p), 0) != 0) | ||
256 | break; | ||
257 | } | ||
258 | if (kt->type != -1) | ||
259 | continue; | ||
260 | } | ||
234 | free(s); | 261 | free(s); |
235 | return 0; | 262 | return 0; |
236 | } | 263 | } |
@@ -798,13 +825,28 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain) | |||
798 | } | 825 | } |
799 | 826 | ||
800 | int | 827 | int |
801 | sshkey_to_blob_buf(const struct sshkey *key, struct sshbuf *b) | 828 | sshkey_putb(const struct sshkey *key, struct sshbuf *b) |
802 | { | 829 | { |
803 | return to_blob_buf(key, b, 0); | 830 | return to_blob_buf(key, b, 0); |
804 | } | 831 | } |
805 | 832 | ||
806 | int | 833 | int |
807 | sshkey_plain_to_blob_buf(const struct sshkey *key, struct sshbuf *b) | 834 | sshkey_puts(const struct sshkey *key, struct sshbuf *b) |
835 | { | ||
836 | struct sshbuf *tmp; | ||
837 | int r; | ||
838 | |||
839 | if ((tmp = sshbuf_new()) == NULL) | ||
840 | return SSH_ERR_ALLOC_FAIL; | ||
841 | r = to_blob_buf(key, tmp, 0); | ||
842 | if (r == 0) | ||
843 | r = sshbuf_put_stringb(b, tmp); | ||
844 | sshbuf_free(tmp); | ||
845 | return r; | ||
846 | } | ||
847 | |||
848 | int | ||
849 | sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b) | ||
808 | { | 850 | { |
809 | return to_blob_buf(key, b, 1); | 851 | return to_blob_buf(key, b, 1); |
810 | } | 852 | } |
@@ -853,29 +895,18 @@ sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) | |||
853 | } | 895 | } |
854 | 896 | ||
855 | int | 897 | int |
856 | sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, | 898 | sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg, |
857 | u_char **retp, size_t *lenp) | 899 | u_char **retp, size_t *lenp) |
858 | { | 900 | { |
859 | u_char *blob = NULL, *ret = NULL; | 901 | u_char *blob = NULL, *ret = NULL; |
860 | size_t blob_len = 0; | 902 | size_t blob_len = 0; |
861 | int hash_alg = -1, r = SSH_ERR_INTERNAL_ERROR; | 903 | int r = SSH_ERR_INTERNAL_ERROR; |
862 | 904 | ||
863 | if (retp != NULL) | 905 | if (retp != NULL) |
864 | *retp = NULL; | 906 | *retp = NULL; |
865 | if (lenp != NULL) | 907 | if (lenp != NULL) |
866 | *lenp = 0; | 908 | *lenp = 0; |
867 | 909 | if (ssh_digest_bytes(dgst_alg) == 0) { | |
868 | switch (dgst_type) { | ||
869 | case SSH_FP_MD5: | ||
870 | hash_alg = SSH_DIGEST_MD5; | ||
871 | break; | ||
872 | case SSH_FP_SHA1: | ||
873 | hash_alg = SSH_DIGEST_SHA1; | ||
874 | break; | ||
875 | case SSH_FP_SHA256: | ||
876 | hash_alg = SSH_DIGEST_SHA256; | ||
877 | break; | ||
878 | default: | ||
879 | r = SSH_ERR_INVALID_ARGUMENT; | 910 | r = SSH_ERR_INVALID_ARGUMENT; |
880 | goto out; | 911 | goto out; |
881 | } | 912 | } |
@@ -900,7 +931,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, | |||
900 | r = SSH_ERR_ALLOC_FAIL; | 931 | r = SSH_ERR_ALLOC_FAIL; |
901 | goto out; | 932 | goto out; |
902 | } | 933 | } |
903 | if ((r = ssh_digest_memory(hash_alg, blob, blob_len, | 934 | if ((r = ssh_digest_memory(dgst_alg, blob, blob_len, |
904 | ret, SSH_DIGEST_MAX_LENGTH)) != 0) | 935 | ret, SSH_DIGEST_MAX_LENGTH)) != 0) |
905 | goto out; | 936 | goto out; |
906 | /* success */ | 937 | /* success */ |
@@ -909,7 +940,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, | |||
909 | ret = NULL; | 940 | ret = NULL; |
910 | } | 941 | } |
911 | if (lenp != NULL) | 942 | if (lenp != NULL) |
912 | *lenp = ssh_digest_bytes(hash_alg); | 943 | *lenp = ssh_digest_bytes(dgst_alg); |
913 | r = 0; | 944 | r = 0; |
914 | out: | 945 | out: |
915 | free(ret); | 946 | free(ret); |
@@ -921,21 +952,45 @@ sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type, | |||
921 | } | 952 | } |
922 | 953 | ||
923 | static char * | 954 | static char * |
924 | fingerprint_hex(u_char *dgst_raw, size_t dgst_raw_len) | 955 | fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len) |
925 | { | 956 | { |
926 | char *retval; | 957 | char *ret; |
927 | size_t i; | 958 | size_t plen = strlen(alg) + 1; |
959 | size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1; | ||
960 | int r; | ||
928 | 961 | ||
929 | if ((retval = calloc(1, dgst_raw_len * 3 + 1)) == NULL) | 962 | if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL) |
963 | return NULL; | ||
964 | strlcpy(ret, alg, rlen); | ||
965 | strlcat(ret, ":", rlen); | ||
966 | if (dgst_raw_len == 0) | ||
967 | return ret; | ||
968 | if ((r = b64_ntop(dgst_raw, dgst_raw_len, | ||
969 | ret + plen, rlen - plen)) == -1) { | ||
970 | explicit_bzero(ret, rlen); | ||
971 | free(ret); | ||
930 | return NULL; | 972 | return NULL; |
931 | for (i = 0; i < dgst_raw_len; i++) { | ||
932 | char hex[4]; | ||
933 | snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); | ||
934 | strlcat(retval, hex, dgst_raw_len * 3 + 1); | ||
935 | } | 973 | } |
974 | /* Trim padding characters from end */ | ||
975 | ret[strcspn(ret, "=")] = '\0'; | ||
976 | return ret; | ||
977 | } | ||
978 | |||
979 | static char * | ||
980 | fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len) | ||
981 | { | ||
982 | char *retval, hex[5]; | ||
983 | size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2; | ||
936 | 984 | ||
937 | /* Remove the trailing ':' character */ | 985 | if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL) |
938 | retval[(dgst_raw_len * 3) - 1] = '\0'; | 986 | return NULL; |
987 | strlcpy(retval, alg, rlen); | ||
988 | strlcat(retval, ":", rlen); | ||
989 | for (i = 0; i < dgst_raw_len; i++) { | ||
990 | snprintf(hex, sizeof(hex), "%s%02x", | ||
991 | i > 0 ? ":" : "", dgst_raw[i]); | ||
992 | strlcat(retval, hex, rlen); | ||
993 | } | ||
939 | return retval; | 994 | return retval; |
940 | } | 995 | } |
941 | 996 | ||
@@ -1021,7 +1076,7 @@ fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len) | |||
1021 | #define FLDSIZE_Y (FLDBASE + 1) | 1076 | #define FLDSIZE_Y (FLDBASE + 1) |
1022 | #define FLDSIZE_X (FLDBASE * 2 + 1) | 1077 | #define FLDSIZE_X (FLDBASE * 2 + 1) |
1023 | static char * | 1078 | static char * |
1024 | fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, | 1079 | fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len, |
1025 | const struct sshkey *k) | 1080 | const struct sshkey *k) |
1026 | { | 1081 | { |
1027 | /* | 1082 | /* |
@@ -1029,9 +1084,9 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, | |||
1029 | * intersects with itself. Matter of taste. | 1084 | * intersects with itself. Matter of taste. |
1030 | */ | 1085 | */ |
1031 | char *augmentation_string = " .o+=*BOX@%&#/^SE"; | 1086 | char *augmentation_string = " .o+=*BOX@%&#/^SE"; |
1032 | char *retval, *p, title[FLDSIZE_X]; | 1087 | char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X]; |
1033 | u_char field[FLDSIZE_X][FLDSIZE_Y]; | 1088 | u_char field[FLDSIZE_X][FLDSIZE_Y]; |
1034 | size_t i, tlen; | 1089 | size_t i, tlen, hlen; |
1035 | u_int b; | 1090 | u_int b; |
1036 | int x, y, r; | 1091 | int x, y, r; |
1037 | size_t len = strlen(augmentation_string) - 1; | 1092 | size_t len = strlen(augmentation_string) - 1; |
@@ -1076,8 +1131,12 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, | |||
1076 | sshkey_type(k), sshkey_size(k)); | 1131 | sshkey_type(k), sshkey_size(k)); |
1077 | /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */ | 1132 | /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */ |
1078 | if (r < 0 || r > (int)sizeof(title)) | 1133 | if (r < 0 || r > (int)sizeof(title)) |
1079 | snprintf(title, sizeof(title), "[%s]", sshkey_type(k)); | 1134 | r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k)); |
1080 | tlen = strlen(title); | 1135 | tlen = (r <= 0) ? 0 : strlen(title); |
1136 | |||
1137 | /* assemble hash ID. */ | ||
1138 | r = snprintf(hash, sizeof(hash), "[%s]", alg); | ||
1139 | hlen = (r <= 0) ? 0 : strlen(hash); | ||
1081 | 1140 | ||
1082 | /* output upper border */ | 1141 | /* output upper border */ |
1083 | p = retval; | 1142 | p = retval; |
@@ -1086,7 +1145,7 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, | |||
1086 | *p++ = '-'; | 1145 | *p++ = '-'; |
1087 | memcpy(p, title, tlen); | 1146 | memcpy(p, title, tlen); |
1088 | p += tlen; | 1147 | p += tlen; |
1089 | for (i = p - retval - 1; i < FLDSIZE_X; i++) | 1148 | for (i += tlen; i < FLDSIZE_X; i++) |
1090 | *p++ = '-'; | 1149 | *p++ = '-'; |
1091 | *p++ = '+'; | 1150 | *p++ = '+'; |
1092 | *p++ = '\n'; | 1151 | *p++ = '\n'; |
@@ -1102,7 +1161,11 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, | |||
1102 | 1161 | ||
1103 | /* output lower border */ | 1162 | /* output lower border */ |
1104 | *p++ = '+'; | 1163 | *p++ = '+'; |
1105 | for (i = 0; i < FLDSIZE_X; i++) | 1164 | for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++) |
1165 | *p++ = '-'; | ||
1166 | memcpy(p, hash, hlen); | ||
1167 | p += hlen; | ||
1168 | for (i += hlen; i < FLDSIZE_X; i++) | ||
1106 | *p++ = '-'; | 1169 | *p++ = '-'; |
1107 | *p++ = '+'; | 1170 | *p++ = '+'; |
1108 | 1171 | ||
@@ -1110,24 +1173,39 @@ fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len, | |||
1110 | } | 1173 | } |
1111 | 1174 | ||
1112 | char * | 1175 | char * |
1113 | sshkey_fingerprint(const struct sshkey *k, enum sshkey_fp_type dgst_type, | 1176 | sshkey_fingerprint(const struct sshkey *k, int dgst_alg, |
1114 | enum sshkey_fp_rep dgst_rep) | 1177 | enum sshkey_fp_rep dgst_rep) |
1115 | { | 1178 | { |
1116 | char *retval = NULL; | 1179 | char *retval = NULL; |
1117 | u_char *dgst_raw; | 1180 | u_char *dgst_raw; |
1118 | size_t dgst_raw_len; | 1181 | size_t dgst_raw_len; |
1119 | 1182 | ||
1120 | if (sshkey_fingerprint_raw(k, dgst_type, &dgst_raw, &dgst_raw_len) != 0) | 1183 | if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0) |
1121 | return NULL; | 1184 | return NULL; |
1122 | switch (dgst_rep) { | 1185 | switch (dgst_rep) { |
1186 | case SSH_FP_DEFAULT: | ||
1187 | if (dgst_alg == SSH_DIGEST_MD5) { | ||
1188 | retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg), | ||
1189 | dgst_raw, dgst_raw_len); | ||
1190 | } else { | ||
1191 | retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg), | ||
1192 | dgst_raw, dgst_raw_len); | ||
1193 | } | ||
1194 | break; | ||
1123 | case SSH_FP_HEX: | 1195 | case SSH_FP_HEX: |
1124 | retval = fingerprint_hex(dgst_raw, dgst_raw_len); | 1196 | retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg), |
1197 | dgst_raw, dgst_raw_len); | ||
1198 | break; | ||
1199 | case SSH_FP_BASE64: | ||
1200 | retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg), | ||
1201 | dgst_raw, dgst_raw_len); | ||
1125 | break; | 1202 | break; |
1126 | case SSH_FP_BUBBLEBABBLE: | 1203 | case SSH_FP_BUBBLEBABBLE: |
1127 | retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len); | 1204 | retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len); |
1128 | break; | 1205 | break; |
1129 | case SSH_FP_RANDOMART: | 1206 | case SSH_FP_RANDOMART: |
1130 | retval = fingerprint_randomart(dgst_raw, dgst_raw_len, k); | 1207 | retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg), |
1208 | dgst_raw, dgst_raw_len, k); | ||
1131 | break; | 1209 | break; |
1132 | default: | 1210 | default: |
1133 | explicit_bzero(dgst_raw, dgst_raw_len); | 1211 | explicit_bzero(dgst_raw, dgst_raw_len); |
@@ -1234,16 +1312,20 @@ sshkey_read(struct sshkey *ret, char **cpp) | |||
1234 | cp = space+1; | 1312 | cp = space+1; |
1235 | if (*cp == '\0') | 1313 | if (*cp == '\0') |
1236 | return SSH_ERR_INVALID_FORMAT; | 1314 | return SSH_ERR_INVALID_FORMAT; |
1237 | if (ret->type == KEY_UNSPEC) { | 1315 | if (ret->type != KEY_UNSPEC && ret->type != type) |
1238 | ret->type = type; | ||
1239 | } else if (ret->type != type) | ||
1240 | return SSH_ERR_KEY_TYPE_MISMATCH; | 1316 | return SSH_ERR_KEY_TYPE_MISMATCH; |
1241 | if ((blob = sshbuf_new()) == NULL) | 1317 | if ((blob = sshbuf_new()) == NULL) |
1242 | return SSH_ERR_ALLOC_FAIL; | 1318 | return SSH_ERR_ALLOC_FAIL; |
1243 | /* trim comment */ | 1319 | /* trim comment */ |
1244 | space = strchr(cp, ' '); | 1320 | space = strchr(cp, ' '); |
1245 | if (space) | 1321 | if (space) { |
1246 | *space = '\0'; | 1322 | /* advance 'space': skip whitespace */ |
1323 | *space++ = '\0'; | ||
1324 | while (*space == ' ' || *space == '\t') | ||
1325 | space++; | ||
1326 | *cpp = space; | ||
1327 | } else | ||
1328 | *cpp = cp + strlen(cp); | ||
1247 | if ((r = sshbuf_b64tod(blob, cp)) != 0) { | 1329 | if ((r = sshbuf_b64tod(blob, cp)) != 0) { |
1248 | sshbuf_free(blob); | 1330 | sshbuf_free(blob); |
1249 | return r; | 1331 | return r; |
@@ -1263,7 +1345,7 @@ sshkey_read(struct sshkey *ret, char **cpp) | |||
1263 | sshkey_free(k); | 1345 | sshkey_free(k); |
1264 | return SSH_ERR_EC_CURVE_MISMATCH; | 1346 | return SSH_ERR_EC_CURVE_MISMATCH; |
1265 | } | 1347 | } |
1266 | /*XXXX*/ | 1348 | ret->type = type; |
1267 | if (sshkey_is_cert(ret)) { | 1349 | if (sshkey_is_cert(ret)) { |
1268 | if (!sshkey_is_cert(k)) { | 1350 | if (!sshkey_is_cert(k)) { |
1269 | sshkey_free(k); | 1351 | sshkey_free(k); |
@@ -1320,12 +1402,6 @@ sshkey_read(struct sshkey *ret, char **cpp) | |||
1320 | sshkey_free(k); | 1402 | sshkey_free(k); |
1321 | if (retval != 0) | 1403 | if (retval != 0) |
1322 | break; | 1404 | break; |
1323 | /* advance cp: skip whitespace and data */ | ||
1324 | while (*cp == ' ' || *cp == '\t') | ||
1325 | cp++; | ||
1326 | while (*cp != '\0' && *cp != ' ' && *cp != '\t') | ||
1327 | cp++; | ||
1328 | *cpp = cp; | ||
1329 | break; | 1405 | break; |
1330 | default: | 1406 | default: |
1331 | return SSH_ERR_INVALID_ARGUMENT; | 1407 | return SSH_ERR_INVALID_ARGUMENT; |
@@ -1390,7 +1466,7 @@ sshkey_write(const struct sshkey *key, FILE *f) | |||
1390 | ret = SSH_ERR_ALLOC_FAIL; | 1466 | ret = SSH_ERR_ALLOC_FAIL; |
1391 | goto out; | 1467 | goto out; |
1392 | } | 1468 | } |
1393 | if ((ret = sshkey_to_blob_buf(key, bb)) != 0) | 1469 | if ((ret = sshkey_putb(key, bb)) != 0) |
1394 | goto out; | 1470 | goto out; |
1395 | if ((uu = sshbuf_dtob64(bb)) == NULL) { | 1471 | if ((uu = sshbuf_dtob64(bb)) == NULL) { |
1396 | ret = SSH_ERR_ALLOC_FAIL; | 1472 | ret = SSH_ERR_ALLOC_FAIL; |
@@ -1767,38 +1843,30 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) | |||
1767 | } | 1843 | } |
1768 | 1844 | ||
1769 | static int | 1845 | static int |
1770 | cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob, | 1846 | cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) |
1771 | size_t blen) | ||
1772 | { | 1847 | { |
1773 | u_char *principals = NULL, *critical = NULL, *exts = NULL; | 1848 | struct sshbuf *principals = NULL, *crit = NULL; |
1774 | u_char *sig_key = NULL, *sig = NULL; | 1849 | struct sshbuf *exts = NULL, *ca = NULL; |
1775 | size_t signed_len, plen, clen, sklen, slen, kidlen, elen; | 1850 | u_char *sig = NULL; |
1776 | struct sshbuf *tmp; | 1851 | size_t signed_len = 0, slen = 0, kidlen = 0; |
1777 | char *principal; | ||
1778 | int ret = SSH_ERR_INTERNAL_ERROR; | 1852 | int ret = SSH_ERR_INTERNAL_ERROR; |
1779 | int v00 = sshkey_cert_is_legacy(key); | 1853 | int v00 = sshkey_cert_is_legacy(key); |
1780 | char **oprincipals; | ||
1781 | |||
1782 | if ((tmp = sshbuf_new()) == NULL) | ||
1783 | return SSH_ERR_ALLOC_FAIL; | ||
1784 | 1854 | ||
1785 | /* Copy the entire key blob for verification and later serialisation */ | 1855 | /* Copy the entire key blob for verification and later serialisation */ |
1786 | if ((ret = sshbuf_put(key->cert->certblob, blob, blen)) != 0) | 1856 | if ((ret = sshbuf_putb(key->cert->certblob, certbuf)) != 0) |
1787 | return ret; | 1857 | return ret; |
1788 | 1858 | ||
1789 | elen = 0; /* Not touched for v00 certs */ | ||
1790 | principals = exts = critical = sig_key = sig = NULL; | ||
1791 | if ((!v00 && (ret = sshbuf_get_u64(b, &key->cert->serial)) != 0) || | 1859 | if ((!v00 && (ret = sshbuf_get_u64(b, &key->cert->serial)) != 0) || |
1792 | (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 || | 1860 | (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 || |
1793 | (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 || | 1861 | (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 || |
1794 | (ret = sshbuf_get_string(b, &principals, &plen)) != 0 || | 1862 | (ret = sshbuf_froms(b, &principals)) != 0 || |
1795 | (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 || | 1863 | (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 || |
1796 | (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 || | 1864 | (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 || |
1797 | (ret = sshbuf_get_string(b, &critical, &clen)) != 0 || | 1865 | (ret = sshbuf_froms(b, &crit)) != 0 || |
1798 | (!v00 && (ret = sshbuf_get_string(b, &exts, &elen)) != 0) || | 1866 | (!v00 && (ret = sshbuf_froms(b, &exts)) != 0) || |
1799 | (v00 && (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0) || | 1867 | (v00 && (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0) || |
1800 | (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || | 1868 | (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || |
1801 | (ret = sshbuf_get_string(b, &sig_key, &sklen)) != 0) { | 1869 | (ret = sshbuf_froms(b, &ca)) != 0) { |
1802 | /* XXX debug print error for ret */ | 1870 | /* XXX debug print error for ret */ |
1803 | ret = SSH_ERR_INVALID_FORMAT; | 1871 | ret = SSH_ERR_INVALID_FORMAT; |
1804 | goto out; | 1872 | goto out; |
@@ -1818,14 +1886,17 @@ cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob, | |||
1818 | goto out; | 1886 | goto out; |
1819 | } | 1887 | } |
1820 | 1888 | ||
1821 | if ((ret = sshbuf_put(tmp, principals, plen)) != 0) | 1889 | /* Parse principals section */ |
1822 | goto out; | 1890 | while (sshbuf_len(principals) > 0) { |
1823 | while (sshbuf_len(tmp) > 0) { | 1891 | char *principal = NULL; |
1892 | char **oprincipals = NULL; | ||
1893 | |||
1824 | if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) { | 1894 | if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) { |
1825 | ret = SSH_ERR_INVALID_FORMAT; | 1895 | ret = SSH_ERR_INVALID_FORMAT; |
1826 | goto out; | 1896 | goto out; |
1827 | } | 1897 | } |
1828 | if ((ret = sshbuf_get_cstring(tmp, &principal, &plen)) != 0) { | 1898 | if ((ret = sshbuf_get_cstring(principals, &principal, |
1899 | NULL)) != 0) { | ||
1829 | ret = SSH_ERR_INVALID_FORMAT; | 1900 | ret = SSH_ERR_INVALID_FORMAT; |
1830 | goto out; | 1901 | goto out; |
1831 | } | 1902 | } |
@@ -1842,38 +1913,38 @@ cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob, | |||
1842 | key->cert->principals[key->cert->nprincipals++] = principal; | 1913 | key->cert->principals[key->cert->nprincipals++] = principal; |
1843 | } | 1914 | } |
1844 | 1915 | ||
1845 | sshbuf_reset(tmp); | 1916 | /* |
1846 | 1917 | * Stash a copies of the critical options and extensions sections | |
1847 | if ((ret = sshbuf_put(key->cert->critical, critical, clen)) != 0 || | 1918 | * for later use. |
1848 | (ret = sshbuf_put(tmp, critical, clen)) != 0) | 1919 | */ |
1920 | if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 || | ||
1921 | (exts != NULL && | ||
1922 | (ret = sshbuf_putb(key->cert->extensions, exts)) != 0)) | ||
1849 | goto out; | 1923 | goto out; |
1850 | 1924 | ||
1851 | /* validate structure */ | 1925 | /* |
1852 | while (sshbuf_len(tmp) != 0) { | 1926 | * Validate critical options and extensions sections format. |
1853 | if ((ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0 || | 1927 | * NB. extensions are not present in v00 certs. |
1854 | (ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0) { | 1928 | */ |
1929 | while (sshbuf_len(crit) != 0) { | ||
1930 | if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 || | ||
1931 | (ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) { | ||
1932 | sshbuf_reset(key->cert->critical); | ||
1855 | ret = SSH_ERR_INVALID_FORMAT; | 1933 | ret = SSH_ERR_INVALID_FORMAT; |
1856 | goto out; | 1934 | goto out; |
1857 | } | 1935 | } |
1858 | } | 1936 | } |
1859 | sshbuf_reset(tmp); | 1937 | while (exts != NULL && sshbuf_len(exts) != 0) { |
1860 | 1938 | if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 || | |
1861 | if ((ret = sshbuf_put(key->cert->extensions, exts, elen)) != 0 || | 1939 | (ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) { |
1862 | (ret = sshbuf_put(tmp, exts, elen)) != 0) | 1940 | sshbuf_reset(key->cert->extensions); |
1863 | goto out; | ||
1864 | |||
1865 | /* validate structure */ | ||
1866 | while (sshbuf_len(tmp) != 0) { | ||
1867 | if ((ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0 || | ||
1868 | (ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0) { | ||
1869 | ret = SSH_ERR_INVALID_FORMAT; | 1941 | ret = SSH_ERR_INVALID_FORMAT; |
1870 | goto out; | 1942 | goto out; |
1871 | } | 1943 | } |
1872 | } | 1944 | } |
1873 | sshbuf_reset(tmp); | ||
1874 | 1945 | ||
1875 | if (sshkey_from_blob_internal(sig_key, sklen, | 1946 | /* Parse CA key and check signature */ |
1876 | &key->cert->signature_key, 0) != 0) { | 1947 | if (sshkey_from_blob_internal(ca, &key->cert->signature_key, 0) != 0) { |
1877 | ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; | 1948 | ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
1878 | goto out; | 1949 | goto out; |
1879 | } | 1950 | } |
@@ -1881,50 +1952,49 @@ cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob, | |||
1881 | ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; | 1952 | ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
1882 | goto out; | 1953 | goto out; |
1883 | } | 1954 | } |
1884 | |||
1885 | if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, | 1955 | if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, |
1886 | sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0) | 1956 | sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0) |
1887 | goto out; | 1957 | goto out; |
1888 | ret = 0; | ||
1889 | 1958 | ||
1959 | /* Success */ | ||
1960 | ret = 0; | ||
1890 | out: | 1961 | out: |
1891 | sshbuf_free(tmp); | 1962 | sshbuf_free(ca); |
1892 | free(principals); | 1963 | sshbuf_free(crit); |
1893 | free(critical); | 1964 | sshbuf_free(exts); |
1894 | free(exts); | 1965 | sshbuf_free(principals); |
1895 | free(sig_key); | ||
1896 | free(sig); | 1966 | free(sig); |
1897 | return ret; | 1967 | return ret; |
1898 | } | 1968 | } |
1899 | 1969 | ||
1900 | static int | 1970 | static int |
1901 | sshkey_from_blob_internal(const u_char *blob, size_t blen, | 1971 | sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, |
1902 | struct sshkey **keyp, int allow_cert) | 1972 | int allow_cert) |
1903 | { | 1973 | { |
1904 | struct sshbuf *b = NULL; | 1974 | int type, ret = SSH_ERR_INTERNAL_ERROR; |
1905 | int type, nid = -1, ret = SSH_ERR_INTERNAL_ERROR; | ||
1906 | char *ktype = NULL, *curve = NULL; | 1975 | char *ktype = NULL, *curve = NULL; |
1907 | struct sshkey *key = NULL; | 1976 | struct sshkey *key = NULL; |
1908 | size_t len; | 1977 | size_t len; |
1909 | u_char *pk = NULL; | 1978 | u_char *pk = NULL; |
1979 | struct sshbuf *copy; | ||
1910 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) | 1980 | #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) |
1911 | EC_POINT *q = NULL; | 1981 | EC_POINT *q = NULL; |
1912 | #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ | 1982 | #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ |
1913 | 1983 | ||
1914 | #ifdef DEBUG_PK /* XXX */ | 1984 | #ifdef DEBUG_PK /* XXX */ |
1915 | dump_base64(stderr, blob, blen); | 1985 | sshbuf_dump(b, stderr); |
1916 | #endif | 1986 | #endif |
1917 | *keyp = NULL; | 1987 | *keyp = NULL; |
1918 | if ((b = sshbuf_from(blob, blen)) == NULL) | 1988 | if ((copy = sshbuf_fromb(b)) == NULL) { |
1919 | return SSH_ERR_ALLOC_FAIL; | 1989 | ret = SSH_ERR_ALLOC_FAIL; |
1990 | goto out; | ||
1991 | } | ||
1920 | if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { | 1992 | if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { |
1921 | ret = SSH_ERR_INVALID_FORMAT; | 1993 | ret = SSH_ERR_INVALID_FORMAT; |
1922 | goto out; | 1994 | goto out; |
1923 | } | 1995 | } |
1924 | 1996 | ||
1925 | type = sshkey_type_from_name(ktype); | 1997 | type = sshkey_type_from_name(ktype); |
1926 | if (sshkey_type_plain(type) == KEY_ECDSA) | ||
1927 | nid = sshkey_ecdsa_nid_from_name(ktype); | ||
1928 | if (!allow_cert && sshkey_type_is_cert(type)) { | 1998 | if (!allow_cert && sshkey_type_is_cert(type)) { |
1929 | ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; | 1999 | ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; |
1930 | goto out; | 2000 | goto out; |
@@ -1932,6 +2002,7 @@ sshkey_from_blob_internal(const u_char *blob, size_t blen, | |||
1932 | switch (type) { | 2002 | switch (type) { |
1933 | #ifdef WITH_OPENSSL | 2003 | #ifdef WITH_OPENSSL |
1934 | case KEY_RSA_CERT: | 2004 | case KEY_RSA_CERT: |
2005 | /* Skip nonce */ | ||
1935 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { | 2006 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { |
1936 | ret = SSH_ERR_INVALID_FORMAT; | 2007 | ret = SSH_ERR_INVALID_FORMAT; |
1937 | goto out; | 2008 | goto out; |
@@ -1953,6 +2024,7 @@ sshkey_from_blob_internal(const u_char *blob, size_t blen, | |||
1953 | #endif | 2024 | #endif |
1954 | break; | 2025 | break; |
1955 | case KEY_DSA_CERT: | 2026 | case KEY_DSA_CERT: |
2027 | /* Skip nonce */ | ||
1956 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { | 2028 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { |
1957 | ret = SSH_ERR_INVALID_FORMAT; | 2029 | ret = SSH_ERR_INVALID_FORMAT; |
1958 | goto out; | 2030 | goto out; |
@@ -1976,6 +2048,7 @@ sshkey_from_blob_internal(const u_char *blob, size_t blen, | |||
1976 | #endif | 2048 | #endif |
1977 | break; | 2049 | break; |
1978 | case KEY_ECDSA_CERT: | 2050 | case KEY_ECDSA_CERT: |
2051 | /* Skip nonce */ | ||
1979 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { | 2052 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { |
1980 | ret = SSH_ERR_INVALID_FORMAT; | 2053 | ret = SSH_ERR_INVALID_FORMAT; |
1981 | goto out; | 2054 | goto out; |
@@ -1987,7 +2060,7 @@ sshkey_from_blob_internal(const u_char *blob, size_t blen, | |||
1987 | ret = SSH_ERR_ALLOC_FAIL; | 2060 | ret = SSH_ERR_ALLOC_FAIL; |
1988 | goto out; | 2061 | goto out; |
1989 | } | 2062 | } |
1990 | key->ecdsa_nid = nid; | 2063 | key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype); |
1991 | if (sshbuf_get_cstring(b, &curve, NULL) != 0) { | 2064 | if (sshbuf_get_cstring(b, &curve, NULL) != 0) { |
1992 | ret = SSH_ERR_INVALID_FORMAT; | 2065 | ret = SSH_ERR_INVALID_FORMAT; |
1993 | goto out; | 2066 | goto out; |
@@ -2028,6 +2101,7 @@ sshkey_from_blob_internal(const u_char *blob, size_t blen, | |||
2028 | # endif /* OPENSSL_HAS_ECC */ | 2101 | # endif /* OPENSSL_HAS_ECC */ |
2029 | #endif /* WITH_OPENSSL */ | 2102 | #endif /* WITH_OPENSSL */ |
2030 | case KEY_ED25519_CERT: | 2103 | case KEY_ED25519_CERT: |
2104 | /* Skip nonce */ | ||
2031 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { | 2105 | if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { |
2032 | ret = SSH_ERR_INVALID_FORMAT; | 2106 | ret = SSH_ERR_INVALID_FORMAT; |
2033 | goto out; | 2107 | goto out; |
@@ -2059,8 +2133,7 @@ sshkey_from_blob_internal(const u_char *blob, size_t blen, | |||
2059 | } | 2133 | } |
2060 | 2134 | ||
2061 | /* Parse certificate potion */ | 2135 | /* Parse certificate potion */ |
2062 | if (sshkey_is_cert(key) && | 2136 | if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0) |
2063 | (ret = cert_parse(b, key, blob, blen)) != 0) | ||
2064 | goto out; | 2137 | goto out; |
2065 | 2138 | ||
2066 | if (key != NULL && sshbuf_len(b) != 0) { | 2139 | if (key != NULL && sshbuf_len(b) != 0) { |
@@ -2071,7 +2144,7 @@ sshkey_from_blob_internal(const u_char *blob, size_t blen, | |||
2071 | *keyp = key; | 2144 | *keyp = key; |
2072 | key = NULL; | 2145 | key = NULL; |
2073 | out: | 2146 | out: |
2074 | sshbuf_free(b); | 2147 | sshbuf_free(copy); |
2075 | sshkey_free(key); | 2148 | sshkey_free(key); |
2076 | free(ktype); | 2149 | free(ktype); |
2077 | free(curve); | 2150 | free(curve); |
@@ -2086,7 +2159,33 @@ sshkey_from_blob_internal(const u_char *blob, size_t blen, | |||
2086 | int | 2159 | int |
2087 | sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp) | 2160 | sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp) |
2088 | { | 2161 | { |
2089 | return sshkey_from_blob_internal(blob, blen, keyp, 1); | 2162 | struct sshbuf *b; |
2163 | int r; | ||
2164 | |||
2165 | if ((b = sshbuf_from(blob, blen)) == NULL) | ||
2166 | return SSH_ERR_ALLOC_FAIL; | ||
2167 | r = sshkey_from_blob_internal(b, keyp, 1); | ||
2168 | sshbuf_free(b); | ||
2169 | return r; | ||
2170 | } | ||
2171 | |||
2172 | int | ||
2173 | sshkey_fromb(struct sshbuf *b, struct sshkey **keyp) | ||
2174 | { | ||
2175 | return sshkey_from_blob_internal(b, keyp, 1); | ||
2176 | } | ||
2177 | |||
2178 | int | ||
2179 | sshkey_froms(struct sshbuf *buf, struct sshkey **keyp) | ||
2180 | { | ||
2181 | struct sshbuf *b; | ||
2182 | int r; | ||
2183 | |||
2184 | if ((r = sshbuf_froms(buf, &b)) != 0) | ||
2185 | return r; | ||
2186 | r = sshkey_from_blob_internal(b, keyp, 1); | ||
2187 | sshbuf_free(b); | ||
2188 | return r; | ||
2090 | } | 2189 | } |
2091 | 2190 | ||
2092 | int | 2191 | int |
@@ -2132,10 +2231,7 @@ sshkey_verify(const struct sshkey *key, | |||
2132 | const u_char *sig, size_t siglen, | 2231 | const u_char *sig, size_t siglen, |
2133 | const u_char *data, size_t dlen, u_int compat) | 2232 | const u_char *data, size_t dlen, u_int compat) |
2134 | { | 2233 | { |
2135 | if (siglen == 0) | 2234 | if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) |
2136 | return -1; | ||
2137 | |||
2138 | if (dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) | ||
2139 | return SSH_ERR_INVALID_ARGUMENT; | 2235 | return SSH_ERR_INVALID_ARGUMENT; |
2140 | switch (key->type) { | 2236 | switch (key->type) { |
2141 | #ifdef WITH_OPENSSL | 2237 | #ifdef WITH_OPENSSL |
@@ -2369,6 +2465,7 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca) | |||
2369 | break; | 2465 | break; |
2370 | default: | 2466 | default: |
2371 | ret = SSH_ERR_INVALID_ARGUMENT; | 2467 | ret = SSH_ERR_INVALID_ARGUMENT; |
2468 | goto out; | ||
2372 | } | 2469 | } |
2373 | 2470 | ||
2374 | /* -v01 certs have a serial number next */ | 2471 | /* -v01 certs have a serial number next */ |
@@ -2594,8 +2691,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
2594 | { | 2691 | { |
2595 | char *tname = NULL, *curve = NULL; | 2692 | char *tname = NULL, *curve = NULL; |
2596 | struct sshkey *k = NULL; | 2693 | struct sshkey *k = NULL; |
2597 | const u_char *cert; | 2694 | size_t pklen = 0, sklen = 0; |
2598 | size_t len, pklen = 0, sklen = 0; | ||
2599 | int type, r = SSH_ERR_INTERNAL_ERROR; | 2695 | int type, r = SSH_ERR_INTERNAL_ERROR; |
2600 | u_char *ed25519_pk = NULL, *ed25519_sk = NULL; | 2696 | u_char *ed25519_pk = NULL, *ed25519_sk = NULL; |
2601 | #ifdef WITH_OPENSSL | 2697 | #ifdef WITH_OPENSSL |
@@ -2623,8 +2719,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
2623 | break; | 2719 | break; |
2624 | case KEY_DSA_CERT_V00: | 2720 | case KEY_DSA_CERT_V00: |
2625 | case KEY_DSA_CERT: | 2721 | case KEY_DSA_CERT: |
2626 | if ((r = sshbuf_get_string_direct(buf, &cert, &len)) != 0 || | 2722 | if ((r = sshkey_froms(buf, &k)) != 0 || |
2627 | (r = sshkey_from_blob(cert, len, &k)) != 0 || | ||
2628 | (r = sshkey_add_private(k)) != 0 || | 2723 | (r = sshkey_add_private(k)) != 0 || |
2629 | (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) | 2724 | (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) |
2630 | goto out; | 2725 | goto out; |
@@ -2667,8 +2762,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
2667 | r = SSH_ERR_LIBCRYPTO_ERROR; | 2762 | r = SSH_ERR_LIBCRYPTO_ERROR; |
2668 | goto out; | 2763 | goto out; |
2669 | } | 2764 | } |
2670 | if ((r = sshbuf_get_string_direct(buf, &cert, &len)) != 0 || | 2765 | if ((r = sshkey_froms(buf, &k)) != 0 || |
2671 | (r = sshkey_from_blob(cert, len, &k)) != 0 || | ||
2672 | (r = sshkey_add_private(k)) != 0 || | 2766 | (r = sshkey_add_private(k)) != 0 || |
2673 | (r = sshbuf_get_bignum2(buf, exponent)) != 0) | 2767 | (r = sshbuf_get_bignum2(buf, exponent)) != 0) |
2674 | goto out; | 2768 | goto out; |
@@ -2698,8 +2792,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
2698 | break; | 2792 | break; |
2699 | case KEY_RSA_CERT_V00: | 2793 | case KEY_RSA_CERT_V00: |
2700 | case KEY_RSA_CERT: | 2794 | case KEY_RSA_CERT: |
2701 | if ((r = sshbuf_get_string_direct(buf, &cert, &len)) != 0 || | 2795 | if ((r = sshkey_froms(buf, &k)) != 0 || |
2702 | (r = sshkey_from_blob(cert, len, &k)) != 0 || | ||
2703 | (r = sshkey_add_private(k)) != 0 || | 2796 | (r = sshkey_add_private(k)) != 0 || |
2704 | (r = sshbuf_get_bignum2(buf, k->rsa->d) != 0) || | 2797 | (r = sshbuf_get_bignum2(buf, k->rsa->d) != 0) || |
2705 | (r = sshbuf_get_bignum2(buf, k->rsa->iqmp) != 0) || | 2798 | (r = sshbuf_get_bignum2(buf, k->rsa->iqmp) != 0) || |
@@ -2726,8 +2819,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | |||
2726 | ed25519_pk = ed25519_sk = NULL; | 2819 | ed25519_pk = ed25519_sk = NULL; |
2727 | break; | 2820 | break; |
2728 | case KEY_ED25519_CERT: | 2821 | case KEY_ED25519_CERT: |
2729 | if ((r = sshbuf_get_string_direct(buf, &cert, &len)) != 0 || | 2822 | if ((r = sshkey_froms(buf, &k)) != 0 || |
2730 | (r = sshkey_from_blob(cert, len, &k)) != 0 || | ||
2731 | (r = sshkey_add_private(k)) != 0 || | 2823 | (r = sshkey_add_private(k)) != 0 || |
2732 | (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || | 2824 | (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || |
2733 | (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) | 2825 | (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) |
@@ -2953,8 +3045,9 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob, | |||
2953 | const char *passphrase, const char *comment, const char *ciphername, | 3045 | const char *passphrase, const char *comment, const char *ciphername, |
2954 | int rounds) | 3046 | int rounds) |
2955 | { | 3047 | { |
2956 | u_char *cp, *b64 = NULL, *key = NULL, *pubkeyblob = NULL; | 3048 | u_char *cp, *key = NULL, *pubkeyblob = NULL; |
2957 | u_char salt[SALT_LEN]; | 3049 | u_char salt[SALT_LEN]; |
3050 | char *b64 = NULL; | ||
2958 | size_t i, pubkeylen, keylen, ivlen, blocksize, authlen; | 3051 | size_t i, pubkeylen, keylen, ivlen, blocksize, authlen; |
2959 | u_int check; | 3052 | u_int check; |
2960 | int r = SSH_ERR_INTERNAL_ERROR; | 3053 | int r = SSH_ERR_INTERNAL_ERROR; |
@@ -3166,7 +3259,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, | |||
3166 | } | 3259 | } |
3167 | 3260 | ||
3168 | /* decode base64 */ | 3261 | /* decode base64 */ |
3169 | if ((r = sshbuf_b64tod(decoded, sshbuf_ptr(encoded))) != 0) | 3262 | if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0) |
3170 | goto out; | 3263 | goto out; |
3171 | 3264 | ||
3172 | /* check magic */ | 3265 | /* check magic */ |
@@ -3482,10 +3575,12 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, | |||
3482 | int force_new_format, const char *new_format_cipher, int new_format_rounds) | 3575 | int force_new_format, const char *new_format_cipher, int new_format_rounds) |
3483 | { | 3576 | { |
3484 | switch (key->type) { | 3577 | switch (key->type) { |
3485 | #ifdef WITH_OPENSSL | 3578 | #ifdef WITH_SSH1 |
3486 | case KEY_RSA1: | 3579 | case KEY_RSA1: |
3487 | return sshkey_private_rsa1_to_blob(key, blob, | 3580 | return sshkey_private_rsa1_to_blob(key, blob, |
3488 | passphrase, comment); | 3581 | passphrase, comment); |
3582 | #endif /* WITH_SSH1 */ | ||
3583 | #ifdef WITH_OPENSSL | ||
3489 | case KEY_DSA: | 3584 | case KEY_DSA: |
3490 | case KEY_ECDSA: | 3585 | case KEY_ECDSA: |
3491 | case KEY_RSA: | 3586 | case KEY_RSA: |
@@ -3691,20 +3786,16 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase, | |||
3691 | #endif /* WITH_SSH1 */ | 3786 | #endif /* WITH_SSH1 */ |
3692 | 3787 | ||
3693 | #ifdef WITH_OPENSSL | 3788 | #ifdef WITH_OPENSSL |
3694 | /* XXX make private once ssh-keysign.c fixed */ | 3789 | static int |
3695 | int | ||
3696 | sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | 3790 | sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, |
3697 | const char *passphrase, struct sshkey **keyp, char **commentp) | 3791 | const char *passphrase, struct sshkey **keyp) |
3698 | { | 3792 | { |
3699 | EVP_PKEY *pk = NULL; | 3793 | EVP_PKEY *pk = NULL; |
3700 | struct sshkey *prv = NULL; | 3794 | struct sshkey *prv = NULL; |
3701 | char *name = "<no key>"; | ||
3702 | BIO *bio = NULL; | 3795 | BIO *bio = NULL; |
3703 | int r; | 3796 | int r; |
3704 | 3797 | ||
3705 | *keyp = NULL; | 3798 | *keyp = NULL; |
3706 | if (commentp != NULL) | ||
3707 | *commentp = NULL; | ||
3708 | 3799 | ||
3709 | if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX) | 3800 | if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX) |
3710 | return SSH_ERR_ALLOC_FAIL; | 3801 | return SSH_ERR_ALLOC_FAIL; |
@@ -3727,7 +3818,6 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | |||
3727 | } | 3818 | } |
3728 | prv->rsa = EVP_PKEY_get1_RSA(pk); | 3819 | prv->rsa = EVP_PKEY_get1_RSA(pk); |
3729 | prv->type = KEY_RSA; | 3820 | prv->type = KEY_RSA; |
3730 | name = "rsa w/o comment"; | ||
3731 | #ifdef DEBUG_PK | 3821 | #ifdef DEBUG_PK |
3732 | RSA_print_fp(stderr, prv->rsa, 8); | 3822 | RSA_print_fp(stderr, prv->rsa, 8); |
3733 | #endif | 3823 | #endif |
@@ -3743,7 +3833,6 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | |||
3743 | } | 3833 | } |
3744 | prv->dsa = EVP_PKEY_get1_DSA(pk); | 3834 | prv->dsa = EVP_PKEY_get1_DSA(pk); |
3745 | prv->type = KEY_DSA; | 3835 | prv->type = KEY_DSA; |
3746 | name = "dsa w/o comment"; | ||
3747 | #ifdef DEBUG_PK | 3836 | #ifdef DEBUG_PK |
3748 | DSA_print_fp(stderr, prv->dsa, 8); | 3837 | DSA_print_fp(stderr, prv->dsa, 8); |
3749 | #endif | 3838 | #endif |
@@ -3765,7 +3854,6 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | |||
3765 | r = SSH_ERR_INVALID_FORMAT; | 3854 | r = SSH_ERR_INVALID_FORMAT; |
3766 | goto out; | 3855 | goto out; |
3767 | } | 3856 | } |
3768 | name = "ecdsa w/o comment"; | ||
3769 | # ifdef DEBUG_PK | 3857 | # ifdef DEBUG_PK |
3770 | if (prv != NULL && prv->ecdsa != NULL) | 3858 | if (prv != NULL && prv->ecdsa != NULL) |
3771 | sshkey_dump_ec_key(prv->ecdsa); | 3859 | sshkey_dump_ec_key(prv->ecdsa); |
@@ -3775,11 +3863,6 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | |||
3775 | r = SSH_ERR_INVALID_FORMAT; | 3863 | r = SSH_ERR_INVALID_FORMAT; |
3776 | goto out; | 3864 | goto out; |
3777 | } | 3865 | } |
3778 | if (commentp != NULL && | ||
3779 | (*commentp = strdup(name)) == NULL) { | ||
3780 | r = SSH_ERR_ALLOC_FAIL; | ||
3781 | goto out; | ||
3782 | } | ||
3783 | r = 0; | 3866 | r = 0; |
3784 | *keyp = prv; | 3867 | *keyp = prv; |
3785 | prv = NULL; | 3868 | prv = NULL; |
@@ -3804,15 +3887,17 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, | |||
3804 | *commentp = NULL; | 3887 | *commentp = NULL; |
3805 | 3888 | ||
3806 | switch (type) { | 3889 | switch (type) { |
3807 | #ifdef WITH_OPENSSL | 3890 | #ifdef WITH_SSH1 |
3808 | case KEY_RSA1: | 3891 | case KEY_RSA1: |
3809 | return sshkey_parse_private_rsa1(blob, passphrase, | 3892 | return sshkey_parse_private_rsa1(blob, passphrase, |
3810 | keyp, commentp); | 3893 | keyp, commentp); |
3894 | #endif /* WITH_SSH1 */ | ||
3895 | #ifdef WITH_OPENSSL | ||
3811 | case KEY_DSA: | 3896 | case KEY_DSA: |
3812 | case KEY_ECDSA: | 3897 | case KEY_ECDSA: |
3813 | case KEY_RSA: | 3898 | case KEY_RSA: |
3814 | return sshkey_parse_private_pem_fileblob(blob, type, passphrase, | 3899 | return sshkey_parse_private_pem_fileblob(blob, type, |
3815 | keyp, commentp); | 3900 | passphrase, keyp); |
3816 | #endif /* WITH_OPENSSL */ | 3901 | #endif /* WITH_OPENSSL */ |
3817 | case KEY_ED25519: | 3902 | case KEY_ED25519: |
3818 | return sshkey_parse_private2(blob, type, passphrase, | 3903 | return sshkey_parse_private2(blob, type, passphrase, |
@@ -3822,8 +3907,8 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, | |||
3822 | commentp)) == 0) | 3907 | commentp)) == 0) |
3823 | return 0; | 3908 | return 0; |
3824 | #ifdef WITH_OPENSSL | 3909 | #ifdef WITH_OPENSSL |
3825 | return sshkey_parse_private_pem_fileblob(blob, type, passphrase, | 3910 | return sshkey_parse_private_pem_fileblob(blob, type, |
3826 | keyp, commentp); | 3911 | passphrase, keyp); |
3827 | #else | 3912 | #else |
3828 | return SSH_ERR_INVALID_FORMAT; | 3913 | return SSH_ERR_INVALID_FORMAT; |
3829 | #endif /* WITH_OPENSSL */ | 3914 | #endif /* WITH_OPENSSL */ |