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