From 93bf894cd276afcf91a1211a724dc7a4b257591f Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Wed, 10 Nov 2021 21:04:00 +0100 Subject: [PATCH] gcrypt: Support RSA OAEP SHA1 encryption/decryption --- .../plugins/gcrypt/gcrypt_plugin.c | 2 + .../plugins/gcrypt/gcrypt_rsa_private_key.c | 58 ++++++++++--------- .../plugins/gcrypt/gcrypt_rsa_public_key.c | 43 ++++++++++---- 3 files changed, 64 insertions(+), 39 deletions(-) diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c index c37cd57e7f..fc4d9467d7 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c @@ -135,6 +135,7 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA1), PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_MD5), PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_PKCS1), + PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_OAEP_SHA1), /* signature verification schemes */ #if GCRYPT_VERSION_NUMBER >= 0x010700 PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PSS), @@ -147,6 +148,7 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA1), PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_MD5), PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_PKCS1), + PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_OAEP_SHA1), /* random numbers */ PLUGIN_REGISTER(RNG, gcrypt_rng_create), PLUGIN_PROVIDE(RNG, RNG_WEAK), diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c index 5bc0a72ec5..5ef7daf610 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c @@ -282,49 +282,53 @@ METHOD(private_key_t, decrypt, bool, { gcry_error_t err; gcry_sexp_t in, out; - chunk_t padded; - u_char *pos = NULL;; + chunk_t label = chunk_empty, decrypted; + u_char *sexp; - if (scheme != ENCRYPT_RSA_PKCS1) + switch (scheme) { - DBG1(DBG_LIB, "encryption scheme %N not supported", - encryption_scheme_names, scheme); - return FALSE; + case ENCRYPT_RSA_PKCS1: + sexp = "(enc-val(flags pkcs1)(rsa(a %b)))"; + break; + case ENCRYPT_RSA_OAEP_SHA1: + sexp = "(enc-val(flags oaep)(rsa(a %b)))"; + break; + default: + DBG1(DBG_LIB, "encryption scheme %N not supported", + encryption_scheme_names, scheme); + return FALSE; } - err = gcry_sexp_build(&in, NULL, "(enc-val(flags)(rsa(a %b)))", - encrypted.len, encrypted.ptr); + + if (scheme == ENCRYPT_RSA_OAEP_SHA1 && params != NULL) + { + label = *(chunk_t *)params; + if (label.len > 0) + { + DBG1(DBG_LIB, "RSA OAEP decryption with a label not supported"); + return FALSE; + } + } + + err = gcry_sexp_build(&in, NULL, sexp, encrypted.len, encrypted.ptr); if (err) { DBG1(DBG_LIB, "building decryption S-expression failed: %s", gpg_strerror(err)); return FALSE; } + err = gcry_pk_decrypt(&out, in, this->key); gcry_sexp_release(in); if (err) { - DBG1(DBG_LIB, "decrypting pkcs1 data failed: %s", gpg_strerror(err)); + DBG1(DBG_LIB, "RSA decryption failed: %s", gpg_strerror(err)); return FALSE; } - padded.ptr = (u_char*)gcry_sexp_nth_data(out, 1, &padded.len); - /* result is padded, but gcrypt strips leading zero: - * 00 | 02 | RANDOM | 00 | DATA */ - if (padded.ptr && padded.len > 2 && padded.ptr[0] == 0x02) - { - pos = memchr(padded.ptr, 0x00, padded.len - 1); - if (pos) - { - pos++; - *plain = chunk_clone(chunk_create( - pos, padded.len - (pos - padded.ptr))); - } - } + + decrypted.ptr = (u_char*)gcry_sexp_nth_data(out, 1, &decrypted.len); + *plain = chunk_clone(decrypted); gcry_sexp_release(out); - if (!pos) - { - DBG1(DBG_LIB, "decrypted data has invalid pkcs1 padding"); - return FALSE; - } + return TRUE; } diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c index 694a969f80..2200a21187 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c @@ -239,36 +239,55 @@ METHOD(public_key_t, encrypt_, bool, private_gcrypt_rsa_public_key_t *this, encryption_scheme_t scheme, void *params, chunk_t plain, chunk_t *encrypted) { - gcry_sexp_t in, out; gcry_error_t err; + gcry_sexp_t in, out; + chunk_t label = chunk_empty; + u_char *sexp; - if (scheme != ENCRYPT_RSA_PKCS1) + switch (scheme) { - DBG1(DBG_LIB, "encryption scheme %N not supported", - encryption_scheme_names, scheme); - return FALSE; + case ENCRYPT_RSA_PKCS1: + sexp = "(data(flags pkcs1)(value %b))"; + break; + case ENCRYPT_RSA_OAEP_SHA1: + sexp = "(data(flags oaep)(value %b))"; + break; + default: + DBG1(DBG_LIB, "encryption scheme %N not supported", + encryption_scheme_names, scheme); + return FALSE; } - /* "pkcs1" uses PKCS 1.5 (section 8.1) block type 2 encryption: - * 00 | 02 | RANDOM | 00 | DATA */ - err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(value %b))", - plain.len, plain.ptr); + + if (scheme == ENCRYPT_RSA_OAEP_SHA1 && params != NULL) + { + label = *(chunk_t *)params; + if (label.len > 0) + { + DBG1(DBG_LIB, "RSA OAEP encryption with a label not supported"); + return FALSE; + } + } + + err = gcry_sexp_build(&in, NULL, sexp, plain.len, plain.ptr); if (err) { DBG1(DBG_LIB, "building encryption S-expression failed: %s", gpg_strerror(err)); return FALSE; } + err = gcry_pk_encrypt(&out, in, this->key); gcry_sexp_release(in); if (err) { - DBG1(DBG_LIB, "encrypting data using pkcs1 failed: %s", - gpg_strerror(err)); + DBG1(DBG_LIB, "RSA encryption failed: %s", gpg_strerror(err)); return FALSE; } + *encrypted = gcrypt_rsa_find_token(out, "a", this->key); gcry_sexp_release(out); - return !!encrypted->len; + + return encrypted->len > 0; } METHOD(public_key_t, get_keysize, int, -- 2.47.2