mirror of
https://github.com/libssh2/libssh2.git
synced 2026-10-24 03:48:58 +03:00
src: add support for chacha20-poly130-encrypted OpenSSH key files
Also: - switch encrypted ECDSA test key to use chacha20-poly1305@openssh.com. - pem: add debug message on decryption error. Follow-up tofd07ca411f#2486 Follow-up to492bc543bb#1426 Closes #2488
This commit is contained in:
18
src/crypt.c
18
src/crypt.c
@@ -78,6 +78,7 @@ struct crypt_ctx {
|
||||
int encrypt;
|
||||
SSH2_CIPHER_T(algo);
|
||||
ssh2_cipher_ctx h;
|
||||
int privkeyfile; /* for chachapoly decrypt */
|
||||
struct chachapoly_ctx chachapoly_ctx;
|
||||
};
|
||||
|
||||
@@ -87,13 +88,14 @@ static int crypt_init(LIBSSH2_SESSION *session,
|
||||
const struct crypt_method *method,
|
||||
unsigned char *iv, int *free_iv,
|
||||
unsigned char *secret, int *free_secret,
|
||||
int encrypt, void **abstract)
|
||||
int encrypt, int privkeyfile, void **abstract)
|
||||
{
|
||||
struct crypt_ctx *ctx = SSH2_ALLOC(session, sizeof(struct crypt_ctx));
|
||||
if(!ctx)
|
||||
return LIBSSH2_ERROR_ALLOC;
|
||||
|
||||
ctx->encrypt = encrypt;
|
||||
ctx->privkeyfile = privkeyfile;
|
||||
ctx->algo = method->algo;
|
||||
if(ssh2_cipher_init(&ctx->h, ctx->algo, iv, secret, encrypt)) {
|
||||
SSH2_FREE(session, ctx);
|
||||
@@ -310,12 +312,12 @@ static int crypt_init_arcfour128(LIBSSH2_SESSION *session,
|
||||
const struct crypt_method *method,
|
||||
unsigned char *iv, int *free_iv,
|
||||
unsigned char *secret, int *free_secret,
|
||||
int encrypt, void **abstract)
|
||||
int encrypt, int privkeyfile, void **abstract)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = crypt_init(session, method, iv, free_iv, secret, free_secret,
|
||||
encrypt, abstract);
|
||||
encrypt, privkeyfile, abstract);
|
||||
if(rc == 0) {
|
||||
struct crypt_ctx *cctx = *(struct crypt_ctx **)abstract;
|
||||
unsigned char block[8];
|
||||
@@ -383,7 +385,8 @@ static int crypt_init_chacha20_poly(LIBSSH2_SESSION *session,
|
||||
const struct crypt_method *method,
|
||||
unsigned char *iv, int *free_iv,
|
||||
unsigned char *secret, int *free_secret,
|
||||
int encrypt, void **abstract)
|
||||
int encrypt, int privkeyfile,
|
||||
void **abstract)
|
||||
{
|
||||
struct crypt_ctx *ctx = SSH2_ALLOC(session, sizeof(struct crypt_ctx));
|
||||
|
||||
@@ -393,6 +396,7 @@ static int crypt_init_chacha20_poly(LIBSSH2_SESSION *session,
|
||||
return LIBSSH2_ERROR_ALLOC;
|
||||
|
||||
ctx->encrypt = encrypt;
|
||||
ctx->privkeyfile = privkeyfile;
|
||||
ctx->algo = method->algo;
|
||||
|
||||
if(chachapoly_init(&ctx->chachapoly_ctx, secret, method->secret_len)) {
|
||||
@@ -430,7 +434,7 @@ static int crypt_encrypt_chacha20_poly_buffer(LIBSSH2_SESSION *session,
|
||||
ret = chachapoly_crypt(&ctx->chachapoly_ctx, seqno, buf, buf,
|
||||
buf_len - 4, 4, ctx->encrypt);
|
||||
}
|
||||
else {
|
||||
else if(!ctx->privkeyfile) {
|
||||
/* buf is full packet including size and auth tag but buf_len
|
||||
does not include size */
|
||||
if(buf_len < 4)
|
||||
@@ -444,6 +448,10 @@ static int crypt_encrypt_chacha20_poly_buffer(LIBSSH2_SESSION *session,
|
||||
if(ret == 0)
|
||||
memmove(buf, buf + 4, buf_len - 4);
|
||||
}
|
||||
else
|
||||
/* for private key decryption */
|
||||
ret = chachapoly_crypt(&ctx->chachapoly_ctx, seqno, buf, buf,
|
||||
buf_len, 0, ctx->encrypt);
|
||||
}
|
||||
|
||||
return ret == 0 ? 0 : 1; /* success: 0, fail: 1 */
|
||||
|
||||
@@ -237,7 +237,7 @@ static int kex_finish(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if(session->local.crypt->init(session, session->local.crypt, iv,
|
||||
&free_iv, secret, &free_secret, 1,
|
||||
&free_iv, secret, &free_secret, 1, 0,
|
||||
&session->local.crypt_abstract)) {
|
||||
SSH2_FREE(session, iv);
|
||||
SSH2_FREE(session, secret);
|
||||
@@ -281,7 +281,7 @@ static int kex_finish(LIBSSH2_SESSION *session,
|
||||
"key exchange");
|
||||
}
|
||||
if(session->remote.crypt->init(session, session->remote.crypt, iv,
|
||||
&free_iv, secret, &free_secret, 0,
|
||||
&free_iv, secret, &free_secret, 0, 0,
|
||||
&session->remote.crypt_abstract)) {
|
||||
SSH2_FREE(session, iv);
|
||||
SSH2_FREE(session, secret);
|
||||
|
||||
@@ -1055,7 +1055,7 @@ struct crypt_method {
|
||||
int (*init)(LIBSSH2_SESSION *session,
|
||||
const struct crypt_method *method, unsigned char *iv,
|
||||
int *free_iv, unsigned char *secret, int *free_secret,
|
||||
int encrypt, void **abstract);
|
||||
int encrypt, int privkeyfile, void **abstract);
|
||||
int (*get_len)(LIBSSH2_SESSION *session, unsigned int seqno,
|
||||
unsigned char *data, size_t data_size, unsigned int *len,
|
||||
void **abstract);
|
||||
|
||||
33
src/pem.c
33
src/pem.c
@@ -297,8 +297,8 @@ int ssh2_pem_parse(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
/* Initialize the decryption */
|
||||
if(method->init(session, method, iv, &free_iv, secret, &free_secret, 0,
|
||||
&abstract)) {
|
||||
if(method->init(session, method, iv, &free_iv, secret,
|
||||
&free_secret, 0, 1, &abstract)) {
|
||||
ssh2_explicit_zero(secret, sizeof(secret));
|
||||
goto out;
|
||||
}
|
||||
@@ -579,19 +579,22 @@ static int pem_parse_data_openssh(LIBSSH2_SESSION *session,
|
||||
goto out;
|
||||
}
|
||||
|
||||
iv_part = SSH2_CALLOC(session, ivlen);
|
||||
if(!iv_part) {
|
||||
ret = ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
"Could not alloc iv part");
|
||||
goto out;
|
||||
if(ivlen) {
|
||||
iv_part = SSH2_CALLOC(session, ivlen);
|
||||
if(!iv_part) {
|
||||
ret = ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
"Could not alloc IV part");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(key_part, key, keylen);
|
||||
memcpy(iv_part, key + keylen, ivlen);
|
||||
if(iv_part)
|
||||
memcpy(iv_part, key + keylen, ivlen);
|
||||
|
||||
/* Initialize the decryption */
|
||||
if(method->init(session, method, iv_part, &free_iv, key_part,
|
||||
&free_secret, 0, &abstract)) {
|
||||
&free_secret, 0, 1, &abstract)) {
|
||||
ret = LIBSSH2_ERROR_DECRYPT;
|
||||
goto out;
|
||||
}
|
||||
@@ -604,9 +607,16 @@ static int pem_parse_data_openssh(LIBSSH2_SESSION *session,
|
||||
}
|
||||
|
||||
if(method->flags & SSH2_CRYPT_FLAG_REQUIRES_FULL_PACKET) {
|
||||
if(!ssh2_check_length(&decoded, method->auth_len)) {
|
||||
ret = ssh2_err(session, LIBSSH2_ERROR_PROTO,
|
||||
"OpenSSH key full packet auth tag missing");
|
||||
method->dtor(session, &abstract);
|
||||
goto out;
|
||||
}
|
||||
if(method->crypt(session, 0, decrypted.data,
|
||||
decrypted.len, &abstract, MIDDLE_BLOCK)) {
|
||||
ret = LIBSSH2_ERROR_DECRYPT;
|
||||
ret = ssh2_err(session, LIBSSH2_ERROR_DECRYPT,
|
||||
"OpenSSH key full packet decrypt failed");
|
||||
method->dtor(session, &abstract);
|
||||
goto out;
|
||||
}
|
||||
@@ -622,7 +632,8 @@ static int pem_parse_data_openssh(LIBSSH2_SESSION *session,
|
||||
*/
|
||||
if(method->crypt(session, 0, decrypted.data + len_decrypted,
|
||||
blocksize, &abstract, MIDDLE_BLOCK)) {
|
||||
ret = LIBSSH2_ERROR_DECRYPT;
|
||||
ret = ssh2_err(session, LIBSSH2_ERROR_DECRYPT,
|
||||
"OpenSSH key decrypt failed");
|
||||
method->dtor(session, &abstract);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ ssh-keygen -t rsa -b 4096 -N '' -m PEM -C 'id_rsa_sha2_512_sign
|
||||
ssh-keygen -t rsa-sha2-512 -I "${id}" -n "${pr}" -s 'openssh_server/ca_rsa' 'keys/id_rsa_sha2_512_signed.pub'
|
||||
|
||||
ssh-keygen -t ecdsa -b 384 -N '' -m RFC4716 -C '' -f 'keys/id_ecdsa' # empty comment
|
||||
ssh-keygen -t ecdsa -b 256 -N "${pw}" -m RFC4716 -C 'id_ecdsa_encrypted' -f 'keys/id_ecdsa_encrypted' -Z aes256-ctr
|
||||
ssh-keygen -t ecdsa -b 256 -N "${pw}" -m RFC4716 -C 'id_ecdsa_encrypted' -f 'keys/id_ecdsa_encrypted' -Z chacha20-poly1305@openssh.com
|
||||
|
||||
ssh-keygen -t ecdsa -b 384 -N '' -m RFC4716 -C 'id_ecdsa_signed' -f 'keys/id_ecdsa_signed'
|
||||
ssh-keygen -I "${id}" -n "${pr}" -s 'openssh_server/ca_ecdsa' 'keys/id_ecdsa_signed.pub'
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABCexYpKz/
|
||||
UV1UYiV/3FlloPAAAAGAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlz
|
||||
dHAyNTYAAABBBOq2ZOQo5aWIsS6eOUHMCtQdg5qNZnIiwLGN76QgJVySA5BZ2gCjPEpnzG
|
||||
kitAXeKA/CA6E9oUrTXLfk5Pt49CgAAACwG6cRJOtaOQ8R6+mruqqbU/Pu6OqX87ulBepH
|
||||
TcKpai4ou1c9WOD6FPbNyPUhrcBYo6qxrYHWMUqxfYnRKJp2UmTLNKjOSU7nY7Z/szTbov
|
||||
XQnAT3Fe3ygcsmOG+HYUtFJGs0vAPZj2l/oiX84hBIX41Zw5TZIHqiRdkHBXWutTNFJ3xk
|
||||
UKr7MT2bFvCcq8DCFW8clUFGsuiHdH96K4MMgT0YanviNjKCY3cEsbnxb+g=
|
||||
b3BlbnNzaC1rZXktdjEAAAAAHWNoYWNoYTIwLXBvbHkxMzA1QG9wZW5zc2guY29tAAAABm
|
||||
JjcnlwdAAAABgAAAAQwXm70kEh9KMQqGC2nC3ImwAAABgAAAABAAAAaAAAABNlY2RzYS1z
|
||||
aGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQS6NmAMYyM3OJyytjoRAAfOojCNl7JkEG
|
||||
hz5dNis8QqVkfNElFMTlclxH3//pcJdh4BPu1KPq81g6zLK2M1uDRiAAAAsAULX7/Io52P
|
||||
CsWJIhzX49Hv37En5dQX+zA+3wqwW9YyN9//Ss6mD7qgLEuRVUY9HijwF3S1yTgah7GBN0
|
||||
YZfkwlOPga1/lgAPZH/LNhtdUfl6PqX4mshMLApdmI9vzLkMCNyHzEqVwjBPWU3ULK3uQl
|
||||
mMX2nPJwiMUAxvyqOtVj9b9ZW7CP2pNrkWW2anb36P3YqLc2vevdJdo1LtY+h8JE0ohoiC
|
||||
lvbA86fzMeLFN/t9+bbvszc/a2ry57D3WQTQ==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
|
||||
@@ -1 +1 @@
|
||||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOq2ZOQo5aWIsS6eOUHMCtQdg5qNZnIiwLGN76QgJVySA5BZ2gCjPEpnzGkitAXeKA/CA6E9oUrTXLfk5Pt49Cg= id_ecdsa_encrypted
|
||||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLo2YAxjIzc4nLK2OhEAB86iMI2XsmQQaHPl02KzxCpWR80SUUxOVyXEff/+lwl2HgE+7Uo+rzWDrMsrYzW4NGI= id_ecdsa_encrypted
|
||||
|
||||
@@ -4,6 +4,6 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC92YlGoc4PJy6DzX916JJZhxkvmkWBLGJdWOL7R9B6
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTe1lN2L/yet0Ma1JzXkQf3t1f+pauALec2FsGZy87KRJW1AOxcTTiePjlFwP1yfSK1lWXQ+uf0b61gkKqqR52FDky24HJWuYlfXlEQMn2d/PNDNVDDbO4TXKyNxxUHFJ6qYMNd4kWjOH+6rmYoWKsWV+3mDRbHagbVPEYL8wep8OTqKOqruVLVPzZyYZkBtn4XOFi6UE8WKiSVdK1Am1O5UxvlD95t32eYch6wQ9azgMqja6spe/L5UJgP83QZFknVC3wPZWkjqomVFql0FpaQclENwyY/OZMxr0cT/f7bCL6s4A/1XpbsGmC0xak4/THHbOn+0LdIej2nGV8JFoR
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDD+1l4u2KtpvsP2EpioqgHjfirT7IIQOQfCsjZCppmLUcPE1/qCC7krqjzaQ3nuKlVEc/pKJrti2oc0tBDp6zzr8pPkmzdMtpjP84RkJZwu6eVZyZqQrjpmwjw7IWVbGoxkKFpWS2ndxCzhoD/F+TW2NcjpwFN53Ktq0SdHVUXU00RlzUiKNTdzanb8vyF3m+PGwIWPX92E2t/31WxRVXwybTdpXSzyz9IIjxMkrSRVa8XzX0EyUzETuiAeU94AWJX5Gu/pFJT6E7VEMQudeN4iI75WYGxrYU1HCOTnsYk/9LCdM7O6ntJIlzul3CwXsD6+B35hu5AJb91RNbHYWUz key_rsa_aes256gcm
|
||||
ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBOiyJJwf+hFJrOkik9IQVxjhhVnI1vKl4BGLj03erLvw4TXXwoZzlPx6J936fU9JvvPw+d8PA4viMEfFbmdbHREKhwi3u1vZrfj0mB8SXw96AcZwX8PAL556wgom+/Qx+Q==
|
||||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOq2ZOQo5aWIsS6eOUHMCtQdg5qNZnIiwLGN76QgJVySA5BZ2gCjPEpnzGkitAXeKA/CA6E9oUrTXLfk5Pt49Cg= id_ecdsa_encrypted
|
||||
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLo2YAxjIzc4nLK2OhEAB86iMI2XsmQQaHPl02KzxCpWR80SUUxOVyXEff/+lwl2HgE+7Uo+rzWDrMsrYzW4NGI= id_ecdsa_encrypted
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFEg0II3zbc1yWGhRzIc5KwTRlmx10RQP0sS63+1oMPi
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICHxEyUTOVHXvdMFARedFQ+H9DW/n8Zy3daKKRqnTDMq
|
||||
|
||||
Reference in New Issue
Block a user