|
Lines 1121-1142
sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
Link Here
|
| 1121 |
return retval; |
1121 |
return retval; |
| 1122 |
} |
1122 |
} |
| 1123 |
|
1123 |
|
|
|
1124 |
static int |
| 1125 |
peek_type_nid(const char *s, size_t l, int *nid) |
| 1126 |
{ |
| 1127 |
const struct keytype *kt; |
| 1124 |
|
1128 |
|
| 1125 |
/* returns 0 ok, and < 0 error */ |
1129 |
for (kt = keytypes; kt->type != -1; kt++) { |
|
|
1130 |
/* Only allow shortname matches for plain key types */ |
| 1131 |
if (kt->name == NULL || strlen(kt->name) != l) |
| 1132 |
continue; |
| 1133 |
if (memcmp(s, kt->name, l) == 0) { |
| 1134 |
*nid = -1; |
| 1135 |
if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT) |
| 1136 |
*nid = kt->nid; |
| 1137 |
return kt->type; |
| 1138 |
} |
| 1139 |
} |
| 1140 |
return KEY_UNSPEC; |
| 1141 |
} |
| 1142 |
|
| 1143 |
|
| 1144 |
/* XXX this can now be made const char * */ |
| 1126 |
int |
1145 |
int |
| 1127 |
sshkey_read(struct sshkey *ret, char **cpp) |
1146 |
sshkey_read(struct sshkey *ret, char **cpp) |
| 1128 |
{ |
1147 |
{ |
| 1129 |
struct sshkey *k; |
1148 |
struct sshkey *k; |
| 1130 |
int retval = SSH_ERR_INVALID_FORMAT; |
1149 |
char *cp, *blobcopy; |
| 1131 |
char *ep, *cp, *space; |
1150 |
size_t space; |
| 1132 |
int r, type, curve_nid = -1; |
1151 |
int r, type, curve_nid = -1; |
| 1133 |
struct sshbuf *blob; |
1152 |
struct sshbuf *blob; |
| 1134 |
|
1153 |
|
| 1135 |
if (ret == NULL) |
1154 |
if (ret == NULL) |
| 1136 |
return SSH_ERR_INVALID_ARGUMENT; |
1155 |
return SSH_ERR_INVALID_ARGUMENT; |
| 1137 |
|
1156 |
|
| 1138 |
cp = *cpp; |
|
|
| 1139 |
|
| 1140 |
switch (ret->type) { |
1157 |
switch (ret->type) { |
| 1141 |
case KEY_UNSPEC: |
1158 |
case KEY_UNSPEC: |
| 1142 |
case KEY_RSA: |
1159 |
case KEY_RSA: |
|
Lines 1147-1259
sshkey_read(struct sshkey *ret, char **cpp)
Link Here
|
| 1147 |
case KEY_ECDSA_CERT: |
1164 |
case KEY_ECDSA_CERT: |
| 1148 |
case KEY_RSA_CERT: |
1165 |
case KEY_RSA_CERT: |
| 1149 |
case KEY_ED25519_CERT: |
1166 |
case KEY_ED25519_CERT: |
| 1150 |
space = strchr(cp, ' '); |
1167 |
break; /* ok */ |
| 1151 |
if (space == NULL) |
|
|
| 1152 |
return SSH_ERR_INVALID_FORMAT; |
| 1153 |
*space = '\0'; |
| 1154 |
type = sshkey_type_from_name(cp); |
| 1155 |
if (sshkey_type_plain(type) == KEY_ECDSA && |
| 1156 |
(curve_nid = sshkey_ecdsa_nid_from_name(cp)) == -1) |
| 1157 |
return SSH_ERR_EC_CURVE_INVALID; |
| 1158 |
*space = ' '; |
| 1159 |
if (type == KEY_UNSPEC) |
| 1160 |
return SSH_ERR_INVALID_FORMAT; |
| 1161 |
cp = space+1; |
| 1162 |
if (*cp == '\0') |
| 1163 |
return SSH_ERR_INVALID_FORMAT; |
| 1164 |
if (ret->type != KEY_UNSPEC && ret->type != type) |
| 1165 |
return SSH_ERR_KEY_TYPE_MISMATCH; |
| 1166 |
if ((blob = sshbuf_new()) == NULL) |
| 1167 |
return SSH_ERR_ALLOC_FAIL; |
| 1168 |
/* trim comment */ |
| 1169 |
space = strchr(cp, ' '); |
| 1170 |
if (space) { |
| 1171 |
/* advance 'space': skip whitespace */ |
| 1172 |
*space++ = '\0'; |
| 1173 |
while (*space == ' ' || *space == '\t') |
| 1174 |
space++; |
| 1175 |
ep = space; |
| 1176 |
} else |
| 1177 |
ep = cp + strlen(cp); |
| 1178 |
if ((r = sshbuf_b64tod(blob, cp)) != 0) { |
| 1179 |
sshbuf_free(blob); |
| 1180 |
return r; |
| 1181 |
} |
| 1182 |
if ((r = sshkey_from_blob(sshbuf_ptr(blob), |
| 1183 |
sshbuf_len(blob), &k)) != 0) { |
| 1184 |
sshbuf_free(blob); |
| 1185 |
return r; |
| 1186 |
} |
| 1187 |
sshbuf_free(blob); |
| 1188 |
if (k->type != type) { |
| 1189 |
sshkey_free(k); |
| 1190 |
return SSH_ERR_KEY_TYPE_MISMATCH; |
| 1191 |
} |
| 1192 |
if (sshkey_type_plain(type) == KEY_ECDSA && |
| 1193 |
curve_nid != k->ecdsa_nid) { |
| 1194 |
sshkey_free(k); |
| 1195 |
return SSH_ERR_EC_CURVE_MISMATCH; |
| 1196 |
} |
| 1197 |
ret->type = type; |
| 1198 |
if (sshkey_is_cert(ret)) { |
| 1199 |
if (!sshkey_is_cert(k)) { |
| 1200 |
sshkey_free(k); |
| 1201 |
return SSH_ERR_EXPECTED_CERT; |
| 1202 |
} |
| 1203 |
if (ret->cert != NULL) |
| 1204 |
cert_free(ret->cert); |
| 1205 |
ret->cert = k->cert; |
| 1206 |
k->cert = NULL; |
| 1207 |
} |
| 1208 |
switch (sshkey_type_plain(ret->type)) { |
| 1209 |
#ifdef WITH_OPENSSL |
| 1210 |
case KEY_RSA: |
| 1211 |
RSA_free(ret->rsa); |
| 1212 |
ret->rsa = k->rsa; |
| 1213 |
k->rsa = NULL; |
| 1214 |
#ifdef DEBUG_PK |
| 1215 |
RSA_print_fp(stderr, ret->rsa, 8); |
| 1216 |
#endif |
| 1217 |
break; |
| 1218 |
case KEY_DSA: |
| 1219 |
DSA_free(ret->dsa); |
| 1220 |
ret->dsa = k->dsa; |
| 1221 |
k->dsa = NULL; |
| 1222 |
#ifdef DEBUG_PK |
| 1223 |
DSA_print_fp(stderr, ret->dsa, 8); |
| 1224 |
#endif |
| 1225 |
break; |
| 1226 |
case KEY_ECDSA: |
| 1227 |
EC_KEY_free(ret->ecdsa); |
| 1228 |
ret->ecdsa = k->ecdsa; |
| 1229 |
ret->ecdsa_nid = k->ecdsa_nid; |
| 1230 |
k->ecdsa = NULL; |
| 1231 |
k->ecdsa_nid = -1; |
| 1232 |
#ifdef DEBUG_PK |
| 1233 |
sshkey_dump_ec_key(ret->ecdsa); |
| 1234 |
#endif |
| 1235 |
break; |
| 1236 |
#endif /* WITH_OPENSSL */ |
| 1237 |
case KEY_ED25519: |
| 1238 |
freezero(ret->ed25519_pk, ED25519_PK_SZ); |
| 1239 |
ret->ed25519_pk = k->ed25519_pk; |
| 1240 |
k->ed25519_pk = NULL; |
| 1241 |
#ifdef DEBUG_PK |
| 1242 |
/* XXX */ |
| 1243 |
#endif |
| 1244 |
break; |
| 1245 |
} |
| 1246 |
*cpp = ep; |
| 1247 |
retval = 0; |
| 1248 |
/*XXXX*/ |
| 1249 |
sshkey_free(k); |
| 1250 |
if (retval != 0) |
| 1251 |
break; |
| 1252 |
break; |
| 1253 |
default: |
1168 |
default: |
| 1254 |
return SSH_ERR_INVALID_ARGUMENT; |
1169 |
return SSH_ERR_INVALID_ARGUMENT; |
| 1255 |
} |
1170 |
} |
| 1256 |
return retval; |
1171 |
|
|
|
1172 |
/* Decode type */ |
| 1173 |
cp = *cpp; |
| 1174 |
space = strcspn(cp, " \t"); |
| 1175 |
if (space == strlen(cp)) |
| 1176 |
return SSH_ERR_INVALID_FORMAT; |
| 1177 |
if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC) |
| 1178 |
return SSH_ERR_INVALID_FORMAT; |
| 1179 |
|
| 1180 |
/* skip whitespace */ |
| 1181 |
for (cp += space; *cp == ' ' || *cp == '\t'; cp++) |
| 1182 |
; |
| 1183 |
if (*cp == '\0') |
| 1184 |
return SSH_ERR_INVALID_FORMAT; |
| 1185 |
if (ret->type != KEY_UNSPEC && ret->type != type) |
| 1186 |
return SSH_ERR_KEY_TYPE_MISMATCH; |
| 1187 |
if ((blob = sshbuf_new()) == NULL) |
| 1188 |
return SSH_ERR_ALLOC_FAIL; |
| 1189 |
|
| 1190 |
/* find end of keyblob and decode */ |
| 1191 |
space = strcspn(cp, " \t"); |
| 1192 |
if ((blobcopy = strndup(cp, space)) == NULL) { |
| 1193 |
sshbuf_free(blob); |
| 1194 |
return SSH_ERR_ALLOC_FAIL; |
| 1195 |
} |
| 1196 |
if ((r = sshbuf_b64tod(blob, blobcopy)) != 0) { |
| 1197 |
free(blobcopy); |
| 1198 |
sshbuf_free(blob); |
| 1199 |
return r; |
| 1200 |
} |
| 1201 |
free(blobcopy); |
| 1202 |
if ((r = sshkey_fromb(blob, &k)) != 0) { |
| 1203 |
sshbuf_free(blob); |
| 1204 |
return r; |
| 1205 |
} |
| 1206 |
sshbuf_free(blob); |
| 1207 |
|
| 1208 |
/* skip whitespace and leave cp at start of comment */ |
| 1209 |
for (cp += space; *cp == ' ' || *cp == '\t'; cp++) |
| 1210 |
; |
| 1211 |
|
| 1212 |
/* ensure type of blob matches type at start of line */ |
| 1213 |
if (k->type != type) { |
| 1214 |
sshkey_free(k); |
| 1215 |
return SSH_ERR_KEY_TYPE_MISMATCH; |
| 1216 |
} |
| 1217 |
if (sshkey_type_plain(type) == KEY_ECDSA && curve_nid != k->ecdsa_nid) { |
| 1218 |
sshkey_free(k); |
| 1219 |
return SSH_ERR_EC_CURVE_MISMATCH; |
| 1220 |
} |
| 1221 |
|
| 1222 |
/* Fill in ret from parsed key */ |
| 1223 |
ret->type = type; |
| 1224 |
if (sshkey_is_cert(ret)) { |
| 1225 |
if (!sshkey_is_cert(k)) { |
| 1226 |
sshkey_free(k); |
| 1227 |
return SSH_ERR_EXPECTED_CERT; |
| 1228 |
} |
| 1229 |
if (ret->cert != NULL) |
| 1230 |
cert_free(ret->cert); |
| 1231 |
ret->cert = k->cert; |
| 1232 |
k->cert = NULL; |
| 1233 |
} |
| 1234 |
switch (sshkey_type_plain(ret->type)) { |
| 1235 |
#ifdef WITH_OPENSSL |
| 1236 |
case KEY_RSA: |
| 1237 |
RSA_free(ret->rsa); |
| 1238 |
ret->rsa = k->rsa; |
| 1239 |
k->rsa = NULL; |
| 1240 |
#ifdef DEBUG_PK |
| 1241 |
RSA_print_fp(stderr, ret->rsa, 8); |
| 1242 |
#endif |
| 1243 |
break; |
| 1244 |
case KEY_DSA: |
| 1245 |
DSA_free(ret->dsa); |
| 1246 |
ret->dsa = k->dsa; |
| 1247 |
k->dsa = NULL; |
| 1248 |
#ifdef DEBUG_PK |
| 1249 |
DSA_print_fp(stderr, ret->dsa, 8); |
| 1250 |
#endif |
| 1251 |
break; |
| 1252 |
case KEY_ECDSA: |
| 1253 |
EC_KEY_free(ret->ecdsa); |
| 1254 |
ret->ecdsa = k->ecdsa; |
| 1255 |
ret->ecdsa_nid = k->ecdsa_nid; |
| 1256 |
k->ecdsa = NULL; |
| 1257 |
k->ecdsa_nid = -1; |
| 1258 |
#ifdef DEBUG_PK |
| 1259 |
sshkey_dump_ec_key(ret->ecdsa); |
| 1260 |
#endif |
| 1261 |
break; |
| 1262 |
#endif /* WITH_OPENSSL */ |
| 1263 |
case KEY_ED25519: |
| 1264 |
freezero(ret->ed25519_pk, ED25519_PK_SZ); |
| 1265 |
ret->ed25519_pk = k->ed25519_pk; |
| 1266 |
k->ed25519_pk = NULL; |
| 1267 |
#ifdef DEBUG_PK |
| 1268 |
/* XXX */ |
| 1269 |
#endif |
| 1270 |
break; |
| 1271 |
} |
| 1272 |
sshkey_free(k); |
| 1273 |
|
| 1274 |
/* success */ |
| 1275 |
*cpp = cp; |
| 1276 |
return 0; |
| 1257 |
} |
1277 |
} |
| 1258 |
|
1278 |
|
| 1259 |
int |
1279 |
int |