summaryrefslogtreecommitdiff
path: root/sshkey.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2018-03-02 02:08:03 +0000
committerDamien Miller <djm@mindrot.org>2018-03-02 14:39:16 +1100
commit94b4e2d29afaaaef89a95289b16c18bf5627f7cd (patch)
tree1eebba00756deab4faa7707d2fc7eb1f075f41df /sshkey.c
parent5886b92968b360623491699247caddfb77a74d80 (diff)
upstream: refactor sshkey_read() to make it a little more, err,
readable. ok markus OpenBSD-Commit-ID: 2e9247b5762fdac3b6335dc606d3822121714c28
Diffstat (limited to 'sshkey.c')
-rw-r--r--sshkey.c248
1 files changed, 135 insertions, 113 deletions
diff --git a/sshkey.c b/sshkey.c
index d8ee70ca0..b7c392bef 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.62 2018/02/23 15:58:38 markus Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.63 2018/03/02 02:08:03 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.
@@ -1215,22 +1215,37 @@ sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
1215 return retval; 1215 return retval;
1216} 1216}
1217 1217
1218static int
1219peek_type_nid(const char *s, size_t l, int *nid)
1220{
1221 const struct keytype *kt;
1222
1223 for (kt = keytypes; kt->type != -1; kt++) {
1224 if (kt->name == NULL || strlen(kt->name) != l)
1225 continue;
1226 if (memcmp(s, kt->name, l) == 0) {
1227 *nid = -1;
1228 if (kt->type == KEY_ECDSA || kt->type == KEY_ECDSA_CERT)
1229 *nid = kt->nid;
1230 return kt->type;
1231 }
1232 }
1233 return KEY_UNSPEC;
1234}
1218 1235
1219/* returns 0 ok, and < 0 error */ 1236/* XXX this can now be made const char * */
1220int 1237int
1221sshkey_read(struct sshkey *ret, char **cpp) 1238sshkey_read(struct sshkey *ret, char **cpp)
1222{ 1239{
1223 struct sshkey *k; 1240 struct sshkey *k;
1224 int retval = SSH_ERR_INVALID_FORMAT; 1241 char *cp, *blobcopy;
1225 char *ep, *cp, *space; 1242 size_t space;
1226 int r, type, curve_nid = -1; 1243 int r, type, curve_nid = -1;
1227 struct sshbuf *blob; 1244 struct sshbuf *blob;
1228 1245
1229 if (ret == NULL) 1246 if (ret == NULL)
1230 return SSH_ERR_INVALID_ARGUMENT; 1247 return SSH_ERR_INVALID_ARGUMENT;
1231 1248
1232 cp = *cpp;
1233
1234 switch (ret->type) { 1249 switch (ret->type) {
1235 case KEY_UNSPEC: 1250 case KEY_UNSPEC:
1236 case KEY_RSA: 1251 case KEY_RSA:
@@ -1245,136 +1260,143 @@ sshkey_read(struct sshkey *ret, char **cpp)
1245 case KEY_XMSS: 1260 case KEY_XMSS:
1246 case KEY_XMSS_CERT: 1261 case KEY_XMSS_CERT:
1247#endif /* WITH_XMSS */ 1262#endif /* WITH_XMSS */
1248 space = strchr(cp, ' '); 1263 break; /* ok */
1249 if (space == NULL) 1264 default:
1250 return SSH_ERR_INVALID_FORMAT; 1265 return SSH_ERR_INVALID_ARGUMENT;
1251 *space = '\0'; 1266 }
1252 type = sshkey_type_from_name(cp); 1267
1253 if (sshkey_type_plain(type) == KEY_ECDSA && 1268 /* Decode type */
1254 (curve_nid = sshkey_ecdsa_nid_from_name(cp)) == -1) 1269 cp = *cpp;
1255 return SSH_ERR_EC_CURVE_INVALID; 1270 space = strcspn(cp, " \t");
1256 *space = ' '; 1271 if (space == strlen(cp))
1257 if (type == KEY_UNSPEC) 1272 return SSH_ERR_INVALID_FORMAT;
1258 return SSH_ERR_INVALID_FORMAT; 1273 if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC)
1259 cp = space+1; 1274 return SSH_ERR_INVALID_FORMAT;
1260 if (*cp == '\0') 1275
1261 return SSH_ERR_INVALID_FORMAT; 1276 /* skip whitespace */
1262 if (ret->type != KEY_UNSPEC && ret->type != type) 1277 for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1263 return SSH_ERR_KEY_TYPE_MISMATCH; 1278 ;
1264 if ((blob = sshbuf_new()) == NULL) 1279 if (*cp == '\0')
1265 return SSH_ERR_ALLOC_FAIL; 1280 return SSH_ERR_INVALID_FORMAT;
1266 /* trim comment */ 1281 if (ret->type != KEY_UNSPEC && ret->type != type)
1267 space = strchr(cp, ' '); 1282 return SSH_ERR_KEY_TYPE_MISMATCH;
1268 if (space) { 1283 if ((blob = sshbuf_new()) == NULL)
1269 /* advance 'space': skip whitespace */ 1284 return SSH_ERR_ALLOC_FAIL;
1270 *space++ = '\0'; 1285
1271 while (*space == ' ' || *space == '\t') 1286 /* find end of keyblob and decode */
1272 space++; 1287 space = strcspn(cp, " \t");
1273 ep = space; 1288 if ((blobcopy = strndup(cp, space)) == NULL) {
1274 } else
1275 ep = cp + strlen(cp);
1276 if ((r = sshbuf_b64tod(blob, cp)) != 0) {
1277 sshbuf_free(blob);
1278 return r;
1279 }
1280 if ((r = sshkey_from_blob(sshbuf_ptr(blob),
1281 sshbuf_len(blob), &k)) != 0) {
1282 sshbuf_free(blob);
1283 return r;
1284 }
1285 sshbuf_free(blob); 1289 sshbuf_free(blob);
1286 if (k->type != type) { 1290 return SSH_ERR_ALLOC_FAIL;
1287 sshkey_free(k); 1291 }
1288 return SSH_ERR_KEY_TYPE_MISMATCH; 1292 if ((r = sshbuf_b64tod(blob, blobcopy)) != 0) {
1289 } 1293 free(blobcopy);
1290 if (sshkey_type_plain(type) == KEY_ECDSA && 1294 sshbuf_free(blob);
1291 curve_nid != k->ecdsa_nid) { 1295 return r;
1296 }
1297 free(blobcopy);
1298 if ((r = sshkey_fromb(blob, &k)) != 0) {
1299 sshbuf_free(blob);
1300 return r;
1301 }
1302 sshbuf_free(blob);
1303
1304 /* skip whitespace and leave cp at start of comment */
1305 for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1306 ;
1307
1308 /* ensure type of blob matches type at start of line */
1309 if (k->type != type) {
1310 sshkey_free(k);
1311 return SSH_ERR_KEY_TYPE_MISMATCH;
1312 }
1313 if (sshkey_type_plain(type) == KEY_ECDSA && curve_nid != k->ecdsa_nid) {
1314 sshkey_free(k);
1315 return SSH_ERR_EC_CURVE_MISMATCH;
1316 }
1317
1318 /* Fill in ret from parsed key */
1319 ret->type = type;
1320 if (sshkey_is_cert(ret)) {
1321 if (!sshkey_is_cert(k)) {
1292 sshkey_free(k); 1322 sshkey_free(k);
1293 return SSH_ERR_EC_CURVE_MISMATCH; 1323 return SSH_ERR_EXPECTED_CERT;
1294 }
1295 ret->type = type;
1296 if (sshkey_is_cert(ret)) {
1297 if (!sshkey_is_cert(k)) {
1298 sshkey_free(k);
1299 return SSH_ERR_EXPECTED_CERT;
1300 }
1301 if (ret->cert != NULL)
1302 cert_free(ret->cert);
1303 ret->cert = k->cert;
1304 k->cert = NULL;
1305 } 1324 }
1306 switch (sshkey_type_plain(ret->type)) { 1325 if (ret->cert != NULL)
1326 cert_free(ret->cert);
1327 ret->cert = k->cert;
1328 k->cert = NULL;
1329 }
1330 switch (sshkey_type_plain(ret->type)) {
1307#ifdef WITH_OPENSSL 1331#ifdef WITH_OPENSSL
1308 case KEY_RSA: 1332 case KEY_RSA:
1309 RSA_free(ret->rsa); 1333 RSA_free(ret->rsa);
1310 ret->rsa = k->rsa; 1334 ret->rsa = k->rsa;
1311 k->rsa = NULL; 1335 k->rsa = NULL;
1312#ifdef DEBUG_PK 1336#ifdef DEBUG_PK
1313 RSA_print_fp(stderr, ret->rsa, 8); 1337 RSA_print_fp(stderr, ret->rsa, 8);
1314#endif 1338#endif
1315 break; 1339 break;
1316 case KEY_DSA: 1340 case KEY_DSA:
1317 DSA_free(ret->dsa); 1341 DSA_free(ret->dsa);
1318 ret->dsa = k->dsa; 1342 ret->dsa = k->dsa;
1319 k->dsa = NULL; 1343 k->dsa = NULL;
1320#ifdef DEBUG_PK 1344#ifdef DEBUG_PK
1321 DSA_print_fp(stderr, ret->dsa, 8); 1345 DSA_print_fp(stderr, ret->dsa, 8);
1322#endif 1346#endif
1323 break; 1347 break;
1324# ifdef OPENSSL_HAS_ECC 1348# ifdef OPENSSL_HAS_ECC
1325 case KEY_ECDSA: 1349 case KEY_ECDSA:
1326 EC_KEY_free(ret->ecdsa); 1350 EC_KEY_free(ret->ecdsa);
1327 ret->ecdsa = k->ecdsa; 1351 ret->ecdsa = k->ecdsa;
1328 ret->ecdsa_nid = k->ecdsa_nid; 1352 ret->ecdsa_nid = k->ecdsa_nid;
1329 k->ecdsa = NULL; 1353 k->ecdsa = NULL;
1330 k->ecdsa_nid = -1; 1354 k->ecdsa_nid = -1;
1331#ifdef DEBUG_PK 1355#ifdef DEBUG_PK
1332 sshkey_dump_ec_key(ret->ecdsa); 1356 sshkey_dump_ec_key(ret->ecdsa);
1333#endif 1357#endif
1334 break; 1358 break;
1335# endif /* OPENSSL_HAS_ECC */ 1359# endif /* OPENSSL_HAS_ECC */
1336#endif /* WITH_OPENSSL */ 1360#endif /* WITH_OPENSSL */
1337 case KEY_ED25519: 1361 case KEY_ED25519:
1338 freezero(ret->ed25519_pk, ED25519_PK_SZ); 1362 freezero(ret->ed25519_pk, ED25519_PK_SZ);
1339 ret->ed25519_pk = k->ed25519_pk; 1363 ret->ed25519_pk = k->ed25519_pk;
1340 k->ed25519_pk = NULL; 1364 k->ed25519_pk = NULL;
1341#ifdef DEBUG_PK 1365#ifdef DEBUG_PK
1342 /* XXX */ 1366 /* XXX */
1343#endif 1367#endif
1344 break; 1368 break;
1345#ifdef WITH_XMSS 1369#ifdef WITH_XMSS
1346 case KEY_XMSS: 1370 case KEY_XMSS:
1347 free(ret->xmss_pk); 1371 free(ret->xmss_pk);
1348 ret->xmss_pk = k->xmss_pk; 1372 ret->xmss_pk = k->xmss_pk;
1349 k->xmss_pk = NULL; 1373 k->xmss_pk = NULL;
1350 free(ret->xmss_state); 1374 free(ret->xmss_state);
1351 ret->xmss_state = k->xmss_state; 1375 ret->xmss_state = k->xmss_state;
1352 k->xmss_state = NULL; 1376 k->xmss_state = NULL;
1353 free(ret->xmss_name); 1377 free(ret->xmss_name);
1354 ret->xmss_name = k->xmss_name; 1378 ret->xmss_name = k->xmss_name;
1355 k->xmss_name = NULL; 1379 k->xmss_name = NULL;
1356 free(ret->xmss_filename); 1380 free(ret->xmss_filename);
1357 ret->xmss_filename = k->xmss_filename; 1381 ret->xmss_filename = k->xmss_filename;
1358 k->xmss_filename = NULL; 1382 k->xmss_filename = NULL;
1359#ifdef DEBUG_PK 1383#ifdef DEBUG_PK
1360 /* XXX */ 1384 /* XXX */
1361#endif 1385#endif
1362 break;
1363#endif /* WITH_XMSS */
1364 }
1365 *cpp = ep;
1366 retval = 0;
1367/*XXXX*/
1368 sshkey_free(k);
1369 if (retval != 0)
1370 break;
1371 break; 1386 break;
1387#endif /* WITH_XMSS */
1372 default: 1388 default:
1373 return SSH_ERR_INVALID_ARGUMENT; 1389 sshkey_free(k);
1390 return SSH_ERR_INTERNAL_ERROR;
1374 } 1391 }
1375 return retval; 1392 sshkey_free(k);
1393
1394 /* success */
1395 *cpp = cp;
1396 return 0;
1376} 1397}
1377 1398
1399
1378int 1400int
1379sshkey_to_base64(const struct sshkey *key, char **b64p) 1401sshkey_to_base64(const struct sshkey *key, char **b64p)
1380{ 1402{