Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PEM support #587

Merged
merged 51 commits into from
Aug 20, 2024
Merged
Changes from 1 commit
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
bee3ad2
add OpenSSH Private Key decryption demo
sjaeckel Sep 26, 2019
fec3d45
add rsa-support
sjaeckel Oct 1, 2019
2ff20d7
add ecdsa key support
sjaeckel Oct 2, 2019
e0046fb
add ssh private testkeys
sjaeckel Oct 2, 2019
350fbc6
refactor & clean-up
sjaeckel Oct 2, 2019
a301ea1
use updated API
sjaeckel Jan 21, 2020
cf71fff
re-factor openssh-privkey demo into library functions
sjaeckel Dec 26, 2021
69c93a8
rename file
sjaeckel Jan 6, 2022
35c306f
add `pk_get_oid_from_asn1()`
sjaeckel Jan 6, 2022
18baa14
add `der_flexi_sequence_cmp()`
sjaeckel Jan 6, 2022
b8cb13f
add `LTC_OID_MAX_STRLEN`
sjaeckel Jan 6, 2022
e9f1db1
add `pkcs8_get_children()`
sjaeckel Jan 6, 2022
3f6f885
re-factor PKCS#8 API a bit
sjaeckel Jan 11, 2022
f036a47
add support for regular PEM files
sjaeckel Jan 12, 2022
370457f
add PEM tests
sjaeckel Jan 12, 2022
464c9b1
add `dsa_import_pkcs8()`
sjaeckel Jan 14, 2022
22a952b
add DSA support to PEM decoder
sjaeckel Jan 14, 2022
d1e48df
Verify that the imported keys match
sjaeckel Jan 16, 2022
a76447f
add file-iterator to `test_process_dir()`
sjaeckel Jan 16, 2022
3e981af
also test FILE-based PEM API's
sjaeckel Jan 16, 2022
87a1758
split-up into multiple C files
sjaeckel Jan 22, 2022
26fbebb
add support for DH keys
sjaeckel Sep 13, 2022
5523ead
disable PEM support on MSVC
sjaeckel Mar 17, 2022
4e46f82
clean-up a bit
sjaeckel Aug 4, 2022
6515822
introduce `pka_key_free()`
sjaeckel Aug 4, 2022
39d4b08
Update docs
sjaeckel Aug 4, 2022
661f584
distinguish between Ed25519 and X25519
sjaeckel Aug 5, 2022
6c24c5c
Add support for `aes256-ctr` encrypted SSH keys
sjaeckel Oct 10, 2023
9333d5c
Use the public key contained within the ssh key
sjaeckel Oct 10, 2023
934abdd
Add "Enter passphrase" support to `openssh-privkey`
sjaeckel Oct 10, 2023
5d86589
Refactor some of the ECC import internals
sjaeckel Aug 4, 2022
f6497d2
Add support for more algos of encrypted PEM files
sjaeckel Oct 10, 2023
cda6211
pem: support for RC5-CBC, RC5-CFB, RC5-OFB
karel-m Oct 12, 2023
23eb8f9
Add support for importing PEM public keys
sjaeckel Oct 13, 2023
928c476
Per default support PEM line lengths up to 80 chars
sjaeckel Oct 13, 2023
ca7b4ee
Add more SSH key tests
sjaeckel Oct 13, 2023
7b5d85d
Calm old Valgrind ...
sjaeckel Oct 14, 2023
8d19047
Add support for more PEM file types + some fixes
sjaeckel Oct 16, 2023
fe3b3e6
Add generic PEM decode APIs
sjaeckel Oct 16, 2023
03515d5
Move password buffer into the library
sjaeckel Oct 17, 2023
9db30df
Make everything compile on MSVC
sjaeckel Oct 17, 2023
02cb0c4
Revert "Move password buffer into the library"
sjaeckel Oct 19, 2023
9579022
Add `free()` function to `password_ctx`
sjaeckel Oct 20, 2023
65e05bf
Update docs
sjaeckel Feb 26, 2024
c0be0aa
Add support for more types of encrypted PEM files
sjaeckel Feb 28, 2024
478f43f
Add support for reading `authorized_keys` files
sjaeckel Feb 29, 2024
ec8ffbb
Update makefiles
sjaeckel Feb 29, 2024
5dec1ee
Fix `make tvs`, add `make pr-check`
sjaeckel Mar 1, 2024
cf79fac
Add support for CFB1 and CFB8
sjaeckel Mar 3, 2024
2613264
We can now also decrypt PEM files encrypted in CFB1 and CFB8 mode
sjaeckel Mar 1, 2024
2594f3a
Update docs
sjaeckel Aug 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor some of the ECC import internals
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
  • Loading branch information
sjaeckel committed Aug 20, 2024
commit 5d8658946b945d9ac30d7471e98247f227d85080
2 changes: 2 additions & 0 deletions src/headers/tomcrypt_private.h
Original file line number Diff line number Diff line change
@@ -382,6 +382,8 @@ int ecc_copy_curve(const ecc_key *srckey, ecc_key *key);
int ecc_set_curve_by_size(int size, ecc_key *key);
int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key);
int ecc_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, ecc_key *key);
int ecc_import_with_curve(const unsigned char *in, unsigned long inlen, int type, ecc_key *key);
int ecc_import_with_oid(const unsigned char *in, unsigned long inlen, unsigned long *oid, unsigned long oid_len, int type, ecc_key *key);

#ifdef LTC_SSH
int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key);
96 changes: 59 additions & 37 deletions src/pk/ecc/ecc_import_openssl.c
Original file line number Diff line number Diff line change
@@ -9,9 +9,7 @@ static int s_ecc_import_private_with_oid(const unsigned char *in, unsigned long
{
ltc_asn1_list seq_priv[4], custom[2];
unsigned char bin_xy[2*ECC_MAXSIZE+2], bin_k[ECC_MAXSIZE];
unsigned long len, pkver = 0, curveoid[16];
char OID[256];
const ltc_ecc_curve *curve;
unsigned long pkver = 0, curveoid[16];
int err;

/* ### try to load private key - no curve parameters just curve OID */
@@ -26,50 +24,44 @@ static int s_ecc_import_private_with_oid(const unsigned char *in, unsigned long

/* try to load private key */
err = der_decode_sequence(in, inlen, seq_priv, 4);
if (err == CRYPT_OK) {
/* load curve parameters for given curve OID */
len = sizeof(OID);
if ((err = pk_oid_num_to_str(curveoid, custom[0].size, OID, &len)) != CRYPT_OK) { goto error; }
if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto error; }
if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto error; }
/* load private+public key */
err = ecc_set_key(bin_k, seq_priv[1].size, PK_PRIVATE, key);
}
if (err != CRYPT_OK) { goto error; }
err = ecc_import_with_oid(bin_k, seq_priv[1].size, curveoid, custom[0].size, PK_PRIVATE, key);
error:
return err;
}

static int s_ecc_import_private_with_curve(const unsigned char *in, unsigned long inlen, ecc_key *key)
int ecc_import_with_oid(const unsigned char *in, unsigned long inlen, unsigned long *oid, unsigned long oid_len, int type, ecc_key *key)
{
char OID[256];
unsigned long len;
const ltc_ecc_curve *curve;
int err;

/* load curve parameters for given curve OID */
len = sizeof(OID);
if ((err = pk_oid_num_to_str(oid, oid_len, OID, &len)) != CRYPT_OK) { goto error; }
if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto error; }
if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto error; }
/* load public key */
err = ecc_set_key(in, inlen, type, key);
error:
return err;
}

int ecc_import_with_curve(const unsigned char *in, unsigned long inlen, int type, ecc_key *key)
{
void *prime, *order, *a, *b, *gx, *gy;
ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4], custom[2];
unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE];
unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128];
unsigned long len_a, len_b, len_k, len_g;
unsigned long len_a, len_b, len_k, len_g, len_xy, len;
unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16];
int err;

if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) {
return err;
}

/* ### try to load private key - curve parameters included */

/* ECPrivateKey SEQUENCE */
LTC_SET_ASN1(custom, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8UL*sizeof(bin_xy));
LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL);
LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k));
LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */
LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */
/* ECParameters SEQUENCE */
LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g));
LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
seq_ecparams[5].optional = 1;
/* FieldID SEQUENCE */
LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
@@ -78,10 +70,33 @@ static int s_ecc_import_private_with_curve(const unsigned char *in, unsigned lon
LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b));
LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, 8UL*sizeof(bin_seed));
seq_curve[2].optional = 1;
/* try to load private key */
err = der_decode_sequence(in, inlen, seq_priv, 4);
/* ECParameters SEQUENCE */
LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g));
LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
seq_ecparams[5].optional = 1;
if (type == PK_PRIVATE) {
/* ECPrivateKey SEQUENCE */
LTC_SET_ASN1(custom, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL);
LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8UL*sizeof(bin_xy));
LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL);
LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k));
LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */
LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */
/* try to load private key */
err = der_decode_sequence(in, inlen, seq_priv, 4);
} else if (type == PK_PUBLIC) {
/* try to load public key */
len_xy = sizeof(bin_xy);
len = 6;
err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len);
} else {
err = CRYPT_PK_INVALID_TYPE;
}
if (err == CRYPT_OK) {
len_k = seq_priv[1].size;
len_a = seq_curve[0].size;
len_b = seq_curve[1].size;
len_g = seq_ecparams[3].size;
@@ -91,8 +106,15 @@ static int s_ecc_import_private_with_curve(const unsigned char *in, unsigned lon
if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; }
/* load curve parameters */
if ((err = ecc_set_curve_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; }
/* load private+public key */
err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key);

if (type == PK_PRIVATE) {
len_k = seq_priv[1].size;
/* load private+public key */
err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key);
} else {
/* load public key */
err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key);
}
}
error:
mp_clear_multi(prime, order, a, b, gx, gy, LTC_NULL);
@@ -111,7 +133,7 @@ int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *ke
goto success;
}

err = s_ecc_import_private_with_curve(in, inlen, key);
err = ecc_import_with_curve(in, inlen, PK_PRIVATE, key);

success:
return err;
70 changes: 4 additions & 66 deletions src/pk/ecc/ecc_import_x509.c
Original file line number Diff line number Diff line change
@@ -8,78 +8,16 @@ static int s_ecc_import_x509_with_oid(const unsigned char *in, unsigned long inl
{
unsigned char bin_xy[2*ECC_MAXSIZE+2];
unsigned long curveoid[16];
unsigned long len_xy, len_oid, len;
char OID[256];
const ltc_ecc_curve *curve;
unsigned long len_xy, len_oid;
int err;

len_xy = sizeof(bin_xy);
len_oid = 16;
err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy,
LTC_ASN1_OBJECT_IDENTIFIER, (void *)curveoid, &len_oid);
if (err == CRYPT_OK) {
/* load curve parameters for given curve OID */
len = sizeof(OID);
if ((err = pk_oid_num_to_str(curveoid, len_oid, OID, &len)) != CRYPT_OK) { goto error; }
if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto error; }
if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto error; }
/* load public key */
err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key);
}
error:
return err;
}

static int s_ecc_import_x509_with_curve(const unsigned char *in, unsigned long inlen, ecc_key *key)
{
void *prime, *order, *a, *b, *gx, *gy;
ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6];
unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE];
unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128];
unsigned long len_a, len_b, len_g, len_xy, len;
unsigned long cofactor = 0, ecver = 0, tmpoid[16];
int err;

if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) {
return err;
}

/* ECParameters SEQUENCE */
LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL);
LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL);
LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL);
LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g));
LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL);
LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL);
seq_ecparams[5].optional = 1;
/* FieldID SEQUENCE */
LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL);
LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL);
/* Curve SEQUENCE */
LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, sizeof(bin_a));
LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b));
LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, 8u*sizeof(bin_seed));
seq_curve[2].optional = 1;
/* try to load public key */
len_xy = sizeof(bin_xy);
len = 6;
err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len);

if (err == CRYPT_OK) {
len_a = seq_curve[0].size;
len_b = seq_curve[1].size;
len_g = seq_ecparams[3].size;
/* create bignums */
if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; }
if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; }
if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; }
/* load curve parameters */
if ((err = ecc_set_curve_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; }
/* load public key */
err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key);
}
if (err != CRYPT_OK) { goto error; }
err = ecc_import_with_oid(bin_xy, len_xy, curveoid, len_oid, PK_PUBLIC, key);
error:
mp_clear_multi(prime, order, a, b, gx, gy, LTC_NULL);
return err;
}

@@ -91,7 +29,7 @@ int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long in
goto success;
}

err = s_ecc_import_x509_with_curve(in, inlen, key);
err = ecc_import_with_curve(in, inlen, PK_PUBLIC, key);

success:
return err;