diff --git a/common/ssh-utils.c b/common/ssh-utils.c
index 3925602a1..38d6e8aa2 100644
--- a/common/ssh-utils.c
+++ b/common/ssh-utils.c
@@ -1,287 +1,354 @@
/* ssh-utils.c - Secure Shell helper functions
* Copyright (C) 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either
*
* - the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* or
*
* - the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* or both in parallel, as here.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
#include
#include
#include
#include
#include
#include "util.h"
#include "ssh-utils.h"
/* Return true if KEYPARMS holds an EdDSA key. */
static int
is_eddsa (gcry_sexp_t keyparms)
{
int result = 0;
gcry_sexp_t list;
const char *s;
size_t n;
int i;
list = gcry_sexp_find_token (keyparms, "flags", 0);
for (i = list ? gcry_sexp_length (list)-1 : 0; i > 0; i--)
{
s = gcry_sexp_nth_data (list, i, &n);
if (!s)
continue; /* Not a data element. */
if (n == 5 && !memcmp (s, "eddsa", 5))
{
result = 1;
break;
}
}
gcry_sexp_release (list);
return result;
}
+/* Dummy functions for es_mopen. */
+static void *dummy_realloc (void *mem, size_t size) { (void) size; return mem; }
+static void dummy_free (void *mem) { (void) mem; }
/* Return the Secure Shell type fingerprint for KEY using digest ALGO.
The length of the fingerprint is returned at R_LEN and the
fingerprint itself at R_FPR. In case of a error code is returned
and NULL stored at R_FPR. */
static gpg_error_t
get_fingerprint (gcry_sexp_t key, int algo,
void **r_fpr, size_t *r_len, int as_string)
{
gpg_error_t err;
gcry_sexp_t list = NULL;
gcry_sexp_t l2 = NULL;
const char *s;
char *name = NULL;
int idx;
const char *elems;
gcry_md_hd_t md = NULL;
int blobmode = 0;
*r_fpr = NULL;
*r_len = 0;
/* Check that the first element is valid. */
list = gcry_sexp_find_token (key, "public-key", 0);
if (!list)
list = gcry_sexp_find_token (key, "private-key", 0);
if (!list)
list = gcry_sexp_find_token (key, "protected-private-key", 0);
if (!list)
list = gcry_sexp_find_token (key, "shadowed-private-key", 0);
if (!list)
{
err = gpg_err_make (default_errsource, GPG_ERR_UNKNOWN_SEXP);
goto leave;
}
l2 = gcry_sexp_cadr (list);
gcry_sexp_release (list);
list = l2;
l2 = NULL;
name = gcry_sexp_nth_string (list, 0);
if (!name)
{
err = gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
goto leave;
}
err = gcry_md_open (&md, algo, 0);
if (err)
goto leave;
switch (gcry_pk_map_name (name))
{
case GCRY_PK_RSA:
elems = "en";
gcry_md_write (md, "\0\0\0\x07ssh-rsa", 11);
break;
case GCRY_PK_DSA:
elems = "pqgy";
gcry_md_write (md, "\0\0\0\x07ssh-dss", 11);
break;
case GCRY_PK_ECC:
if (is_eddsa (list))
{
elems = "q";
blobmode = 1;
/* For now there is just one curve, thus no need to switch
on it. */
gcry_md_write (md, "\0\0\0\x0b" "ssh-ed25519", 15);
}
else
{
/* We only support the 3 standard curves for now. It is
just a quick hack. */
elems = "q";
gcry_md_write (md, "\0\0\0\x13" "ecdsa-sha2-nistp", 20);
l2 = gcry_sexp_find_token (list, "curve", 0);
if (!l2)
elems = "";
else
{
gcry_free (name);
name = gcry_sexp_nth_string (l2, 1);
gcry_sexp_release (l2);
l2 = NULL;
if (!name)
elems = "";
else if (!strcmp (name, "NIST P-256")||!strcmp (name, "nistp256"))
gcry_md_write (md, "256\0\0\0\x08nistp256", 15);
else if (!strcmp (name, "NIST P-384")||!strcmp (name, "nistp384"))
gcry_md_write (md, "384\0\0\0\x08nistp384", 15);
else if (!strcmp (name, "NIST P-521")||!strcmp (name, "nistp521"))
gcry_md_write (md, "521\0\0\0\x08nistp521", 15);
else
elems = "";
}
if (!*elems)
err = gpg_err_make (default_errsource, GPG_ERR_UNKNOWN_CURVE);
}
break;
default:
elems = "";
err = gpg_err_make (default_errsource, GPG_ERR_PUBKEY_ALGO);
break;
}
if (err)
goto leave;
for (idx = 0, s = elems; *s; s++, idx++)
{
l2 = gcry_sexp_find_token (list, s, 1);
if (!l2)
{
err = gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
goto leave;
}
if (blobmode)
{
const char *blob;
size_t bloblen;
unsigned char lenbuf[4];
blob = gcry_sexp_nth_data (l2, 1, &bloblen);
if (!blob)
{
err = gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
goto leave;
}
blob++;
bloblen--;
lenbuf[0] = bloblen >> 24;
lenbuf[1] = bloblen >> 16;
lenbuf[2] = bloblen >> 8;
lenbuf[3] = bloblen;
gcry_md_write (md, lenbuf, 4);
gcry_md_write (md, blob, bloblen);
}
else
{
gcry_mpi_t a;
unsigned char *buf;
size_t buflen;
a = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
gcry_sexp_release (l2);
l2 = NULL;
if (!a)
{
err = gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
goto leave;
}
err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, &buf, &buflen, a);
gcry_mpi_release (a);
if (err)
goto leave;
gcry_md_write (md, buf, buflen);
gcry_free (buf);
}
}
if (as_string)
{
- *r_fpr = (algo == GCRY_MD_MD5 ? bin2hexcolon : /* XXX we need base64 */ bin2hex)
- (gcry_md_read (md, algo), gcry_md_get_algo_dlen (algo), NULL);
+ const char *algo_name;
+ char *fpr;
+
+ /* Prefix string with the algorithm name and a colon. */
+ algo_name = gcry_md_algo_name (algo);
+ *r_fpr = xtrymalloc (strlen (algo_name) + 1 + 3 * gcry_md_get_algo_dlen (algo) + 1);
+ if (*r_fpr == NULL)
+ {
+ err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
+ goto leave;
+ }
+
+ strncpy (*r_fpr, algo_name, strlen (algo_name));
+ fpr = (char *) *r_fpr + strlen (algo_name);
+ *fpr++ = ':';
+
+ if (algo == GCRY_MD_MD5)
+ {
+ bin2hexcolon (gcry_md_read (md, algo), gcry_md_get_algo_dlen (algo), fpr);
+ strlwr (fpr);
+ }
+ else
+ {
+ struct b64state b64s;
+ estream_t stream;
+ char *p;
+ long int len;
+
+ /* Write the base64-encoded hash to fpr. */
+ stream = es_mopen (fpr, 3 * gcry_md_get_algo_dlen (algo) + 1, 0,
+ 0, dummy_realloc, dummy_free, "w");
+ if (stream == NULL)
+ {
+ err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
+ goto leave;
+ }
+
+ err = b64enc_start_es (&b64s, stream, "");
+ if (err)
+ {
+ es_fclose (stream);
+ goto leave;
+ }
+
+ err = b64enc_write (&b64s,
+ gcry_md_read (md, algo), gcry_md_get_algo_dlen (algo));
+ if (err)
+ {
+ es_fclose (stream);
+ goto leave;
+ }
+
+ /* Finish, get the length, and close the stream. */
+ err = b64enc_finish (&b64s);
+ len = es_ftell (stream);
+ es_fclose (stream);
+ if (err)
+ goto leave;
+
+ /* Terminate. */
+ fpr[len] = 0;
+
+ /* Strip the trailing padding characters. */
+ for (p = fpr + len - 1; p > fpr && *p == '='; p--)
+ *p = 0;
+ }
+
*r_len = strlen (*r_fpr) + 1;
- strlwr (*r_fpr);
}
else
{
*r_len = gcry_md_get_algo_dlen (algo);
*r_fpr = xtrymalloc (*r_len);
if (!*r_fpr)
{
err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
goto leave;
}
memcpy (*r_fpr, gcry_md_read (md, algo), *r_len);
}
err = 0;
leave:
gcry_free (name);
gcry_sexp_release (l2);
gcry_md_close (md);
gcry_sexp_release (list);
return err;
}
/* Return the Secure Shell type fingerprint for KEY using digest ALGO.
The length of the fingerprint is returned at R_LEN and the
fingerprint itself at R_FPR. In case of an error an error code is
returned and NULL stored at R_FPR. */
gpg_error_t
ssh_get_fingerprint (gcry_sexp_t key, int algo,
void **r_fpr, size_t *r_len)
{
return get_fingerprint (key, algo, r_fpr, r_len, 0);
}
/* Return the Secure Shell type fingerprint for KEY using digest ALGO
as a string. The fingerprint is mallcoed and stored at R_FPRSTR.
In case of an error an error code is returned and NULL stored at
R_FPRSTR. */
gpg_error_t
ssh_get_fingerprint_string (gcry_sexp_t key, int algo, char **r_fprstr)
{
gpg_error_t err;
size_t dummy;
void *string;
err = get_fingerprint (key, algo, &string, &dummy, 1);
*r_fprstr = string;
return err;
}
diff --git a/common/t-ssh-utils.c b/common/t-ssh-utils.c
index a4e948fe6..1c9b87b1a 100644
--- a/common/t-ssh-utils.c
+++ b/common/t-ssh-utils.c
@@ -1,314 +1,391 @@
/* t-ssh-utils.c - Module test for ssh-utils.c
* Copyright (C) 2011 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
#include
#include
#include
#include
#include
#include
#include "util.h"
#include "ssh-utils.h"
-static struct { const char *key; const char *fpr; } sample_keys[] = {
+static struct
+{
+ const char *key;
+ const char *fpr_md5;
+ const char *fpr_sha256;
+} sample_keys[] = {
{ "(protected-private-key "
"(rsa "
"(n #"
"00D88E47BCE0DA99D6180E8A9F4E6A673CC16F5BB6CF930E0E868BAABA715A8E1D3E2BEA"
"5477170E1F6CAFC0F8907B9892993C70AC476BBB301669F68EE0593532FB522DD60755A3"
"2F8B08649E856271A7F9BCB25F29554DF11707F812EA377683A99DD4698C4DBF797A0ABF"
"43C8EBB364B9FFC9EE78CBEA348C590507A4EA390312153DDD905EC4F1A63D5DA56C08FD"
"C3F6E5707BFC5DBDC09D19723B1AC6E466906F13AA2ECDBD258148F86C980D45CF233415"
"38C5857C2CF0B4C9AB2B4E6A4517FF084FDB009A33553A68907A29691B6FAE994E864F78"
"7B83F714730BEDB0AF1723D636E034D73EB7EC9BA127BB4BE80FD805813E3F45E7FAE514"
"AD2ECA9607#)"
"(e \"#\")"
"(protected openpgp-s2k3-sha1-aes-cbc "
"("
"(sha1 #B5847F9A2DB4E0C5# \"5242880\")"
"#342D81BDE21301F18FDCE169A99A47C5#)"
"#23512602219EC7A97DBA89347CCD59D2072D80CE3F7DD6C97A058B83DAB3C829D97DF5"
"DFE9181F27DBF58258C4CDBD562A5B20BB5BC35EDCA7B1E57B8CDBF92D798F46EE5567BD"
"8A67EF3BE09908A49D41AA166A3398B64227BC75021C69A8FE8354E2903EF52DC91B1FE3"
"EF9558E5C2D34CF38BFC29E99A49AE30B0C22CE81EE14FC71E986E7C7CB5FCF807433FDA"
"EF1D00985767265BA0BE333754E44CCF622CBB98A029D78A6A9AADBC24613127B6448350"
"23DA355ED31CF089DD11A7FC6003CEEB53FB327A05604D053C99996F9E01CB355983F66E"
"7BEB9687A9277BBF440ED5FAF1A8396C9B06C9B47BA7A994E1931B08DAD34449952CD343"
"9A691477682C324EA07CCCE5DF0F0E9DAEFAE3A4717AACA6DC18ED91DD5A820C924BD36B"
"B3BA85BD63B3180C7F94EE58956940621280B9628FA5CC560BB14331AF1A7B5B499F8F03"
"0ED464ABD4E26C5FD610697EDD0FD1203983E73418F3776568A613D3CEFF17199473052A"
"18807A6F5C52A2A643185801D087EE4DC930ABEEB67C5B8A1CB2F29D0ACBD855972BEC0B"
"DE6E52387CFCC54B4C2B87EE947C97173BFCAE3E2658EB819D87F542C9A9FE6C410D08F5"
"3CD5451FB50253F4A848DFE136B3A5861D58B76A26A7E3E4E7A8F8D4BD5B80430674A6B9"
"A2C8EDD53DB37865D1ACBB07E1758DFF64A944E0126F948BF088C0FC0C3607E39522EC94"
"91483A90D9498D7F6C3C8720124C7E3F6E271E78E1CFFB4EF64F070F7424F30372A07D02"
"2355D8B17BB0DEBCBE101F621E0526551A35A56830D74E0F5BD6313DF114D1E46D4844AA"
"E4EB6268637D04B27D200D7F40AFA9AD2CFAA5415E5FC08358FFA79A9E743CCDF6668FE5"
"D79FA03D61941E57244F066A31F1C9D6A34DC62BC738C52B604F00B19EB9FD0173F3B139"
"42932066B7DC94DC4C563392F798A1CE2D5D75B8FF93E440433263CFB7016143A9923CD9"
"634E964A8056946F462B06F320F44449D85B07FA26A324505C858274F89EDBD8346950DE"
"5F#)"
"(protected-at \"20110720T135431\")"
")"
"(comment passphrase_is_abc)"
")",
- "c7:c6:a7:ec:04:6c:87:59:54:f2:88:58:09:e0:f2:b1"
+ "MD5:c7:c6:a7:ec:04:6c:87:59:54:f2:88:58:09:e0:f2:b1",
+ "SHA256:ksKb4DKk2SFX56GRtpt0szBnyjiYARSb2FNlUb7snnE"
},
{
"(protected-private-key "
"(dsa "
"(p #00FC7DC086F4517079BCCFA7FD229477FE88B0231038DFC21B29CCBD74C6F6FE04FD"
"7248C0473D5028BE106D7A7C8F54B269225789E781763527D1432CD46E416C2D14DDCA70"
"27DA4B92D1E222B5BDF4B9C8C761CACCFBD108F7729412E8835653BE5073447287A6BDEB"
"4645A5411752405EE7F503E44B1DFDCA6054CD3C44630B#)"
"(q #00D498505BF0E7EE01239EB51F2B400B8EF6329B17#)"
"(g #00A127B3DD5106F0A463312E42ECB83790E6F3BEA7AC3FAF7A42FB2C00F376323676"
"C9E48984F0D4AC3FE5856F1C2765E9BC3C8A5C9C9CD3166C057E82569D187C48591AA66B"
"8966BFF2B827BE36BD0BA4B895B42136F1381D52DDA708B2A3D181F648228DFFFEB153DA"
"ACCAEBB51EF08A7807CD628024CEFF96FEE97DE95C8CBE#)"
"(y #008E2B0915A3A299D83B4333C848C5D312F25903773E8C4D50691CAF81C3B768FA41"
"7D19F0FD437B377CCF51D3AE598649656D4D74D210CDBC2B76209B16EAAFCB14D6F4D691"
"20164885852AF1CEBB4D8602AD6755DFA7163645B4DB7926CD44D2DD9F840BFEF57F3DB0"
"933C85EB6B0AAC20BC67E73F47B8DDBEC8EFAA64286EF1#)"
"(protected openpgp-s2k3-sha1-aes-cbc "
"("
"(sha1 \"ü¿jy²üa4\" \"5242880\")"
"#FF12BEE0B03F842349717AE1AB6D7AC2#)"
"#95570487C8B5C49492D4E662259F2CF9B6D7E64F728F17A1FE1B2DA616E5976FE32861E"
"C4B1F0DA03D9006C432CF2136871266E9444377ACEF04340B36B4550B5C1E4CC69AD4380"
"A709FB0DAA5104A8B#)"
"(protected-at \"20110720T142801\")"
")"
"(comment sample_dsa_passphrase_is_abc)"
")",
- "2d:b1:70:1a:04:9e:41:a3:ce:27:a5:c7:22:fe:3a:a3"
+ "MD5:2d:b1:70:1a:04:9e:41:a3:ce:27:a5:c7:22:fe:3a:a3",
+ "SHA256:z8+8HEuD/5QpegGS4tSK02dJF+a6o2V67VM2gOPz9oQ"
},
{ /* OpenSSH 6.7p1 generated key: */
"(protected-private-key "
"(ecdsa "
"(curve \"NIST P-256\")"
"(q #041F17ED5E3D637181DFA68157270F94A46C089B6F5D4518564600551C0A60A063B3"
"31EDE027A23CAB58A5BAD469600229DC8DED06380A92F86460ED400F963319#)"
"(protected openpgp-s2k3-sha1-aes-cbc "
"("
"(sha1 #43F887516D94A502# \"20971520\")"
"#B135DEDA02CF36F126BA661FB22A35CF#)"
"#37E74BEC054B17723C106BA69214CFDA245512E40F4848ECF5719E3700002C940BC7EEC"
"283537CA4D8779107E07F03AAA9FAF155BA9BF6286080C35EF72DDAAF303FD9069475B03"
"C99D9FC93C58CD83A852964D2C7BFD1D803E2ECD1331937C3#)"
"(protected-at \"20150922T071259\")"
")"
"(comment \"ecdsa w/o comment\")"
")", /* Passphrase="abc" */
- "93:4f:08:02:7d:cb:16:9b:0c:39:21:4b:cf:28:5a:19"
+ "MD5:93:4f:08:02:7d:cb:16:9b:0c:39:21:4b:cf:28:5a:19",
+ "SHA256:zSj4uXfE1hlQnESD2LO723fMGXsNwzHrfqOfqep37is"
},
{ /* OpenSSH 6.7p1 generated key: */
"(protected-private-key "
"(ecdsa "
"(curve \"NIST P-384\") "
"(q #04B6E747AC2F179F96088D1DB58EB8600BB23FAEF5F58EFE712A7478FB7BF735"
"B015EA2DFBBA965D8C6EB135A2B9B9599D65BF0167D2DB6ABF00F641F0F5FC15A4C3"
"EFE432DA331B7C8A66D6C4C2B0EBB5ED11A80301C4E57C1EBD25665CEBF123#)"
"(protected openpgp-s2k3-sha1-aes-cbc "
"("
"(sha1 #3B13710B67D756EA# \"20971520\")"
"#720599AC095BF1BD73ED72F49FB77BFA#)"
"#F1A522F4533E3A6E40821D67CEA6C28A7FF07ACA4BEE81E0F39193B2E469E0C583D"
"A42E0E2D52ADB5ACFAB9C4CA7F1C3556FD7FD2770717FB3CE7C59474A3E2A7AF3D93"
"9EC01E067DAAA60D3D355D9BABCCD1F013E8637C555DDFA61F8FA5AFB010FF02979D"
"35BBBEED71BFD8BB508F7#)"
"(protected-at \"20150922T070806\")"
")"
"(comment \"ecdsa w/o comment\")"
")", /* Passphrase="abc" */
- "a3:cb:44:c8:56:15:25:62:85:fd:e8:04:7a:26:dc:76"
+ "MD5:a3:cb:44:c8:56:15:25:62:85:fd:e8:04:7a:26:dc:76",
+ "SHA256:JuQh5fjduynuuTEwI9C6yAKK1NnLX9PPd7TP0qZfbGs"
},
{ /* OpenSSH 6.7p1 generated key: */
"(protected-private-key "
"(ecdsa "
"(curve \"NIST P-521\")"
"(q #04005E460058F37DB5ADA670040203C4D7E18D9FC8A7087165904A4E25EE5EEE"
"3046406D922616DA7E71016A1CB9E57A45E3D3727D7C8DF0F11AE2BD75FAD3355CAA"
"E1019D89D33CC77424E5DA233588207444FC9F67BBE428A9528B7DC77AF8261A1D45"
"ACC1A657C99E361E93C1E5C0F214104C18807670F4CDC1E038B7C950FDBAAECB40#)"
"(protected openpgp-s2k3-sha1-aes-cbc "
"("
"(sha1 #FB2E36984DE2E17C# \"19737600\")"
"#85DB6445B37012F9A449E5AC0D5017E9#)"
"#B4C7CCDFE9B5D32B31BA7C763B80485A62EBF34FD68D8E306DA75FD2BDDBABAA098"
"9B51972BA3B731DA5261E0ADC3FAEF9BB4C8284C53D3E88E738AEF1490941903A5B2"
"9F3747E83C4D80B6A89E0B7BDEE5C6638332F4AAEA5983F760B2887A43A1C4BE0564"
"3F72C6943987D97FDAA7D9C235C6D31973A2400DA9BAB564A16EA#)"
"(protected-at \"20150922T075611\")"
")"
"(comment \"ecdsa w/o comment\")"
")", /* Passphrase="abc" */
- "1e:a6:94:ab:bd:81:73:5f:22:bc:0e:c7:89:f6:68:df"
+ "MD5:1e:a6:94:ab:bd:81:73:5f:22:bc:0e:c7:89:f6:68:df",
+ "SHA256:+pbRyYa2UBwDki1k4Wziu2CKrdJIbZM/hOWOQ/sNe/0"
},
{ /* OpenSSH 6.7p1 generated key: */
"(protected-private-key "
"(ecc "
"(curve Ed25519)"
"(flags eddsa)"
"(q #40A3577AA7830C50EBC15B538E9505DB2F0D2FFCD57EA477DD83dcaea530f3c277#)"
"(protected openpgp-s2k3-sha1-aes-cbc "
"("
"(sha1 #FA8123F1A37CBC1F# \"3812352\")"
"#7671C7387E2DD931CC62C35CBBE08A28#)"
"#75e928f4698172b61dffe9ef2ada1d3473f690f3879c5386e2717e5b2fa46884"
"b189ee409827aab0ff37f62996e040b5fa7e75fc4d8152c8734e2e648dff90c9"
"e8c3e39ea7485618d05c34b1b74ff59676e9a3d932245cc101b5904777a09f86#)"
"(protected-at \"20150928T050210\")"
")"
"(comment \"eddsa w/o comment\")"
")", /* Passphrase="abc" */
- "f1:fa:c8:a6:40:bb:b9:a1:65:d7:62:65:ac:26:78:0e"
+ "MD5:f1:fa:c8:a6:40:bb:b9:a1:65:d7:62:65:ac:26:78:0e",
+ "SHA256:yhwBfYnTOnSXcWf1EOPo+oIIpNJ6w/bG36udZ96MmsQ"
},
{
NULL,
NULL
}
};
static char *
read_file (const char *fname, size_t *r_length)
{
FILE *fp;
char *buf;
size_t buflen;
struct stat st;
fp = fopen (fname, "rb");
if (!fp)
{
fprintf (stderr, "%s:%d: can't open '%s': %s\n",
__FILE__, __LINE__, fname, strerror (errno));
exit (1);
}
if (fstat (fileno(fp), &st))
{
fprintf (stderr, "%s:%d: can't stat '%s': %s\n",
__FILE__, __LINE__, fname, strerror (errno));
exit (1);
}
buflen = st.st_size;
buf = xmalloc (buflen+1);
if (fread (buf, buflen, 1, fp) != 1)
{
fprintf (stderr, "%s:%d: error reading '%s': %s\n",
__FILE__, __LINE__, fname, strerror (errno));
exit (1);
}
fclose (fp);
*r_length = buflen;
return buf;
}
static gcry_sexp_t
read_key (const char *fname)
{
gpg_error_t err;
char *buf;
size_t buflen;
gcry_sexp_t key;
buf = read_file (fname, &buflen);
err = gcry_sexp_sscan (&key, NULL, buf, buflen);
if (err)
{
fprintf (stderr, "%s:%d: gcry_sexp_sscan failed: %s\n",
__FILE__, __LINE__, gpg_strerror (err));
exit (1); \
}
xfree (buf);
return key;
}
int
main (int argc, char **argv)
{
gpg_error_t err;
gcry_sexp_t key;
char *string;
int idx;
- if (argc == 2)
+ /* --dump-keys dumps the keys as KEYGRIP.key.IDX. Useful to compute
+ fingerprints to enhance the test vectors. */
+ if (argc == 2 && strcmp (argv[1], "--dump-keys") == 0)
+ for (idx=0; sample_keys[idx].key; idx++)
+ {
+ FILE *s;
+ char *name;
+ char grip[20];
+ char *hexgrip;
+
+ err = keygrip_from_canon_sexp (sample_keys[idx].key,
+ strlen (sample_keys[idx].key),
+ grip);
+ if (err)
+ {
+ fprintf (stderr, "%s:%d: error computing keygrip: %s\n",
+ __FILE__, __LINE__, gpg_strerror (err));
+ exit (1);
+ }
+ hexgrip = bin2hex (grip, 20, NULL);
+
+ name = xtryasprintf ("%s.key.%d", hexgrip, idx);
+ s = fopen (name, "w");
+ if (s == NULL)
+ {
+ fprintf (stderr, "%s:%d: error opening file: %s\n",
+ __FILE__, __LINE__, gpg_strerror (gpg_error_from_syserror ()));
+ exit (1);
+ }
+ xfree (name);
+ fprintf (s, "%s", sample_keys[idx].key);
+ fclose (s);
+ }
+ else if (argc == 2)
{
key = read_key (argv[1]);
+
err = ssh_get_fingerprint_string (key, GCRY_MD_MD5, &string);
if (err)
{
fprintf (stderr, "%s:%d: error getting fingerprint: %s\n",
__FILE__, __LINE__, gpg_strerror (err));
exit (1);
}
puts (string);
xfree (string);
+
+ err = ssh_get_fingerprint_string (key, GCRY_MD_SHA256, &string);
+ if (err)
+ {
+ fprintf (stderr, "%s:%d: error getting fingerprint: %s\n",
+ __FILE__, __LINE__, gpg_strerror (err));
+ exit (1);
+ }
+ puts (string);
+ xfree (string);
+
gcry_sexp_release (key);
}
else
{
for (idx=0; sample_keys[idx].key; idx++)
{
err = gcry_sexp_sscan (&key, NULL, sample_keys[idx].key,
strlen (sample_keys[idx].key));
if (err)
{
fprintf (stderr, "%s:%d: gcry_sexp_sscan failed for "
"sample key %d: %s\n",
__FILE__, __LINE__, idx, gpg_strerror (err));
exit (1);
}
err = ssh_get_fingerprint_string (key, GCRY_MD_MD5, &string);
- gcry_sexp_release (key);
if (err)
{
fprintf (stderr, "%s:%d: error getting fingerprint for "
"sample key %d: %s\n",
__FILE__, __LINE__, idx, gpg_strerror (err));
exit (1);
}
- if (strcmp (string, sample_keys[idx].fpr))
+ if (strcmp (string, sample_keys[idx].fpr_md5))
+ {
+ fprintf (stderr, "%s:%d: fingerprint mismatch for "
+ "sample key %d\n",
+ __FILE__, __LINE__, idx);
+ fprintf (stderr, "want: %s\n got: %s\n",
+ sample_keys[idx].fpr_md5, string);
+ exit (1);
+ }
+ xfree (string);
+
+ err = ssh_get_fingerprint_string (key, GCRY_MD_SHA256, &string);
+ if (err)
+ {
+ fprintf (stderr, "%s:%d: error getting fingerprint for "
+ "sample key %d: %s\n",
+ __FILE__, __LINE__, idx, gpg_strerror (err));
+ exit (1);
+ }
+
+ if (strcmp (string, sample_keys[idx].fpr_sha256))
{
fprintf (stderr, "%s:%d: fingerprint mismatch for "
"sample key %d\n",
__FILE__, __LINE__, idx);
fprintf (stderr, "want: %s\n got: %s\n",
- sample_keys[idx].fpr, string);
+ sample_keys[idx].fpr_sha256, string);
exit (1);
}
xfree (string);
+
+ gcry_sexp_release (key);
}
}
return 0;
}