Bug 1647671 - Update RNP to snapshot from 2020-06-19. r=rjl

Differential Revision: https://phabricator.services.mozilla.com/D80628

--HG--
extra : rebase_source : c2d62f5083055daa73c37316d391ea029893c5a2
This commit is contained in:
Kai Engert 2020-06-23 12:32:22 +02:00
Родитель bdf29458a7
Коммит 66eff79245
32 изменённых файлов: 1634 добавлений и 246 удалений

2
third_party/README.rnp поставляемый
Просмотреть файл

@ -1,7 +1,7 @@
Directory ./rnp contains a copy of rnp which has been obtained from:
https://github.com/rnpgp/rnp
[commit b9335cee8cb346b567b8bfdb93e851618c6deb4a]
[commit ac07057820ece92ddab52536f4a78d7d5bb71ba7]
For licensing information, please refer to the included documentation.

Просмотреть файл

@ -206,7 +206,7 @@ pgp_key_t *rnp_key_store_import_signature(rnp_key_store_t * keyring,
const pgp_signature_t * sig,
pgp_sig_import_status_t *status);
bool rnp_key_store_remove_key(rnp_key_store_t *, const pgp_key_t *);
bool rnp_key_store_remove_key(rnp_key_store_t *, const pgp_key_t *, bool);
pgp_key_t *rnp_key_store_get_key_by_id(rnp_key_store_t *, const unsigned char *, pgp_key_t *);

175
third_party/rnp/include/rnp/rnp.h поставляемый
Просмотреть файл

@ -46,6 +46,7 @@ typedef uint32_t rnp_result_t;
#define RNP_KEY_REMOVE_PUBLIC (1U << 0)
#define RNP_KEY_REMOVE_SECRET (1U << 1)
#define RNP_KEY_REMOVE_SUBKEYS (1U << 2)
#define RNP_KEY_UNLOAD_PUBLIC (1U << 0)
#define RNP_KEY_UNLOAD_SECRET (1U << 1)
@ -170,6 +171,8 @@ typedef struct rnp_op_encrypt_st * rnp_op_encrypt_t;
typedef struct rnp_identifier_iterator_st *rnp_identifier_iterator_t;
typedef struct rnp_uid_handle_st * rnp_uid_handle_t;
typedef struct rnp_signature_handle_st * rnp_signature_handle_t;
typedef struct rnp_recipient_handle_st * rnp_recipient_handle_t;
typedef struct rnp_symenc_handle_st * rnp_symenc_handle_t;
/* Callbacks */
/**
@ -884,7 +887,8 @@ rnp_result_t rnp_key_revoke(rnp_key_handle_t key,
* Note: you need to call rnp_save_keys() to write updated keyring(s) out.
* Other handles of the same key should not be used after this call.
* @param key pointer to the key handle.
* @param flags see RNP_KEY_REMOVE_* constants.
* @param flags see RNP_KEY_REMOVE_* constants. Flag RNP_REMOVE_SUBKEYS will work only for
* primary key, and remove all of it's subkeys as well.
* @return RNP_SUCCESS or error code if failed.
*/
rnp_result_t rnp_key_remove(rnp_key_handle_t key, uint32_t flags);
@ -1640,6 +1644,173 @@ rnp_result_t rnp_op_verify_get_signature_at(rnp_op_verify_t op,
*/
rnp_result_t rnp_op_verify_get_file_info(rnp_op_verify_t op, char **filename, uint32_t *mtime);
/**
* @brief Get data protection (encryption) mode, used in processed message.
*
* @param op opaque verification context. Must be initialized and have execute() called on it.
* @param mode on success string with mode will be stored here. Caller is responsible for
* freeing it using the rnp_buffer_free() call. May be NULL if information is not
* needed. Currently defined values are as following:
* - none : message was not protected/encrypted
* - cfb : message was encrypted in CFB mode without the MDC
* - cfb-mdc : message was encrypted in CFB mode and protected with MDC
* - aead-ocb : message was encrypted in AEAD-OCB mode
* - aead-eax : message was encrypted in AEAD-EAX mode
* @param cipher symmetric cipher, used for data encryption. May be NULL if information is not
* needed. Must be freed by rnp_buffer_free() call.
* @param valid true if message integrity protection was used (i.e. MDC or AEAD), and it was
* validated successfully. Otherwise (even for raw cfb mode) will be false. May be
* NULL if information is not needed.
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_op_verify_get_protection_info(rnp_op_verify_t op,
char ** mode,
char ** cipher,
bool * valid);
/**
* @brief Get number of public keys (recipients) to whom message was encrypted to.
*
* @param op opaque verification context. Must be initialized and have execute() called on it.
* @param count on success number of keys will be stored here. Cannot be NULL.
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_op_verify_get_recipient_count(rnp_op_verify_t op, size_t *count);
/**
* @brief Get the recipient's handle, used to decrypt message.
*
* @param op opaque verification context. Must be initialized and have execute() called on it.
* @param recipient pointer to the opaque handle context. Cannot be NULL. If recipient's key
* was used to decrypt a message then handle will be stored here, otherwise
* it will be set to NULL.
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_op_verify_get_used_recipient(rnp_op_verify_t op,
rnp_recipient_handle_t *recipient);
/**
* @brief Get the recipient's handle by index.
*
* @param op opaque verification context. Must be initialized and have execute() called on it.
* @param idx zero-based index in array.
* @param recipient pointer to the opaque handle context. Cannot be NULL. On success handle
* will be stored here.
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_op_verify_get_recipient_at(rnp_op_verify_t op,
size_t idx,
rnp_recipient_handle_t *recipient);
/**
* @brief Get recipient's keyid.
*
* @param recipient recipient's handle, obtained via rnp_op_verify_get_used_recipient() or
* rnp_op_verify_get_recipient_at() function call. Cannot be NULL.
* @param keyid on success pointer to NULL-terminated string with hex-encoded keyid will be
* stored here. Cannot be NULL. Must be freed using the rnp_buffer_destroy().
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_recipient_get_keyid(rnp_recipient_handle_t recipient, char **keyid);
/**
* @brief Get recipient's key algorithm.
*
* @param recipient recipient's handle, obtained via rnp_op_verify_get_used_recipient() or
* rnp_op_verify_get_recipient_at() function call. Cannot be NULL.
* @param alg on success pointer to NULL-terminated string with algorithm will be stored here.
* Cannot be NULL. Must be freed using the rnp_buffer_destroy().
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_recipient_get_alg(rnp_recipient_handle_t recipient, char **alg);
/**
* @brief Get number of symenc entries (i.e. passwords), to which message was encrypted.
*
* @param op opaque verification context. Must be initialized and have execute() called on it.
* @param count on success number of keys will be stored here. Cannot be NULL.
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_op_verify_get_symenc_count(rnp_op_verify_t op, size_t *count);
/**
* @brief Get the symenc handle, used to decrypt a message.
*
* @param op opaque verification context. Must be initialized and have execute() called on it.
* @param symenc pointer to the opaque symenc context. Cannot be NULL. If password was used to
* decrypt a message then handle will be stored here, otherwise it will be set to
* NULL.
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_op_verify_get_used_symenc(rnp_op_verify_t op, rnp_symenc_handle_t *symenc);
/**
* @brief Get the symenc handle by index.
*
* @param op opaque verification context. Must be initialized and have execute() called on it.
* @param idx zero-based index in array.
* @param symenc pointer to the opaque handle context. Cannot be NULL. On success handle
* will be stored here.
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_op_verify_get_symenc_at(rnp_op_verify_t op,
size_t idx,
rnp_symenc_handle_t *symenc);
/**
* @brief Get the symmetric cipher, used to encrypt data encryption key.
* Note: if message is encrypted with only one passphrase and without public keys, then
* key, derived from password, may be used to encrypt the whole message.
* @param symenc opaque handle, cannot be NULL.
* @param cipher NULL-terminated string with cipher's name will be stored here. Cannot be NULL.
* Must be freed using the rnp_buffer_destroy().
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_symenc_get_cipher(rnp_symenc_handle_t symenc, char **cipher);
/**
* @brief Get AEAD algorithm if it was used to encrypt data encryption key.
*
* @param symenc opaque handle, cannot be NULL.
* @param alg NULL-terminated string with AEAD algorithm name will be stored here. If AEAD was
* not used then it will contain string 'None'. Must be freed using the
* rnp_buffer_destroy().
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_symenc_get_aead_alg(rnp_symenc_handle_t symenc, char **alg);
/**
* @brief Get hash algorithm, used to derive key from the passphrase.
*
* @param symenc opaque handle, cannot be NULL.
* @param alg NULL-terminated string with hash algorithm name will be stored here. Cannot be
* NULL. Must be freed using the rnp_buffer_destroy().
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_symenc_get_hash_alg(rnp_symenc_handle_t symenc, char **alg);
/**
* @brief Get string-to-key type, used to derive password.
*
* @param symenc opaque handle, cannot be NULL.
* @param type NULL-terminated string with s2k type will be stored here. Currently following
* types are available: 'Simple', 'Salted', 'Iterated and salted'. Please note that
* first two are considered weak and should not be used. Must be freed using the
* rnp_buffer_destroy().
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_symenc_get_s2k_type(rnp_symenc_handle_t symenc, char **type);
/**
* @brief Get number of iterations in iterated-and-salted S2K, if it was used.
*
* @param symenc opaque handle, cannot be NULL.
* @param iterations on success number of iterations will be stored here. Cannot be NULL.
* If non-iterated s2k was used then will be set to 0.
* @return RNP_SUCCESS if call succeeded, or error code otherwise.
*/
rnp_result_t rnp_symenc_get_s2k_iterations(rnp_symenc_handle_t symenc, uint32_t *iterations);
/** @brief Free resources allocated in verification context.
* @param op opaque verification context. Must be initialized.
* @return RNP_SUCCESS if call succeeded.
@ -2101,8 +2272,6 @@ rnp_result_t rnp_identifier_iterator_destroy(rnp_identifier_iterator_t it);
#if defined(__cplusplus)
}
#include "utils.h"
#endif
/** Algorithm Strings

3
third_party/rnp/src/examples/sign.c поставляемый
Просмотреть файл

@ -25,7 +25,6 @@
*/
#include <rnp/rnp.h>
#include <repgp/repgp_def.h>
#include <string.h>
#include <time.h>
@ -166,4 +165,4 @@ int
main(int argc, char **argv)
{
return ffi_sign();
}
}

49
third_party/rnp/src/lib/CMakeLists.txt поставляемый
Просмотреть файл

@ -206,7 +206,7 @@ install(
COMPONENT
development
DESTINATION
"${CMAKE_INSTALL_INCLUDEDIR}/${LIBRNP_INCLUDEDIR}"
"${CMAKE_INSTALL_INCLUDEDIR}/${LIBRNP_INCLUDEDIR}/rnp"
RENAME
rnp.h
)
@ -216,7 +216,7 @@ install(
COMPONENT
development
DESTINATION
"${CMAKE_INSTALL_INCLUDEDIR}/${LIBRNP_INCLUDEDIR}"
"${CMAKE_INSTALL_INCLUDEDIR}/${LIBRNP_INCLUDEDIR}/rnp"
RENAME
rnp_err.h
)
@ -249,9 +249,54 @@ install (
COMPONENT development
)
function(get_linked_libs libsvar dirsvar tgt)
get_target_property(imported ${tgt} IMPORTED)
list(APPEND visited_targets ${tgt})
if (imported)
get_target_property(linkedlibs ${tgt} INTERFACE_LINK_LIBRARIES)
else()
get_target_property(linkedlibs ${tgt} LINK_LIBRARIES)
endif()
set(libs)
foreach (lib ${linkedlibs})
if (TARGET ${lib})
list(FIND visited_targets ${lib} visited)
if (${visited} EQUAL -1)
# library
get_target_property(liblocation ${lib} LOCATION)
get_filename_component(linkedlib ${liblocation} NAME_WE)
string(REGEX REPLACE "^${CMAKE_SHARED_LIBRARY_PREFIX}" "" linkedlib ${linkedlib})
get_linked_libs(linkedlibs libdirs ${lib})
list(APPEND libs ${linkedlib} ${linkedlibs})
# directory
get_filename_component(libdir ${liblocation} DIRECTORY)
list(FIND ${dirsvar} ${libdir} seendir)
if (${seendir} EQUAL -1)
list(APPEND ${dirsvar} ${libdir} ${libdirs})
endif()
endif()
endif()
endforeach()
set(visited_targets ${visited_targets} PARENT_SCOPE)
set(${libsvar} ${libs} PARENT_SCOPE)
set(${dirsvar} ${${dirsvar}} PARENT_SCOPE)
endfunction()
get_linked_libs(libs dirs librnp)
set(linkercmd)
foreach (dir ${dirs})
string(APPEND linkercmd "-L${dir} ")
endforeach()
foreach (lib ${libs})
string(APPEND linkercmd "-l${lib} ")
endforeach()
string(STRIP "${linkercmd}" linkercmd)
set(LIBRNP_PRIVATE_LIBS ${linkercmd})
# create a pkgconfig .pc too
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
get_target_property(LIBRNP_OUTPUT_NAME librnp OUTPUT_NAME)
configure_file(
"${PROJECT_SOURCE_DIR}/cmake/librnp.pc.in"
"${PROJECT_BINARY_DIR}/librnp-${PROJECT_VERSION_MAJOR}.pc"

9
third_party/rnp/src/lib/config.h.in поставляемый
Просмотреть файл

@ -24,7 +24,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#define PACKAGE_STRING "rnp 0.13.1+git20200609.b9335cee.MZLA"
#define PACKAGE_STRING "rnp 0.13.1+git20200619.ac070578.MZLA"
#define PACKAGE_BUGREPORT "https://bugzilla.mozilla.org/enter_bug.cgi?product=Thunderbird"
#undef HAVE_BZLIB_H
@ -48,3 +48,10 @@
#undef HAVE__O_BINARY
#undef HAVE__TEMPNAM
/* Macro _GLIBCXX_USE_CXX11_ABI was first introduced with GCC 5.0, which
* we assume to be bundled with a sane implementation of std::regex. */
#if !defined(__GNUC__) || defined(_GLIBCXX_USE_CXX11_ABI)
#define RNP_USE_STD_REGEX 1
#endif

28
third_party/rnp/src/lib/ffi-priv-types.h поставляемый
Просмотреть файл

@ -49,6 +49,21 @@ struct rnp_signature_handle_st {
bool own_sig;
};
struct rnp_recipient_handle_st {
rnp_ffi_t ffi;
uint8_t keyid[PGP_KEY_ID_SIZE];
pgp_pubkey_alg_t palg;
};
struct rnp_symenc_handle_st {
rnp_ffi_t ffi;
pgp_symm_alg_t alg;
pgp_hash_alg_t halg;
pgp_s2k_specifier_t s2k_type;
uint32_t iterations;
pgp_aead_alg_t aalg;
};
struct rnp_ffi_st {
FILE * errs;
rnp_key_store_t * pubring;
@ -132,6 +147,19 @@ struct rnp_op_verify_st {
size_t signature_count;
char * filename;
uint32_t file_mtime;
/* encryption information */
bool encrypted;
bool mdc;
bool validated;
pgp_aead_alg_t aead;
pgp_symm_alg_t salg;
/* recipient/symenc information */
rnp_recipient_handle_t recipients;
size_t recipient_count;
rnp_recipient_handle_t used_recipient;
rnp_symenc_handle_t symencs;
size_t symenc_count;
rnp_symenc_handle_t used_symenc;
};
struct rnp_op_encrypt_st {

9
third_party/rnp/src/lib/pgp-key.cpp поставляемый
Просмотреть файл

@ -1310,6 +1310,15 @@ pgp_key_add_subkey_grip(pgp_key_t *key, const pgp_key_grip_t &grip)
}
}
void
pgp_key_remove_subkey_grip(pgp_key_t *key, const pgp_key_grip_t &grip)
{
auto it = std::find(key->subkey_grips.begin(), key->subkey_grips.end(), grip);
if (it != key->subkey_grips.end()) {
key->subkey_grips.erase(it);
}
}
const pgp_key_grip_t &
pgp_key_get_subkey_grip(const pgp_key_t *key, size_t idx)
{

8
third_party/rnp/src/lib/pgp-key.h поставляемый
Просмотреть файл

@ -327,6 +327,14 @@ size_t pgp_key_get_subkey_count(const pgp_key_t *key);
*/
bool pgp_key_add_subkey_grip(pgp_key_t *key, const pgp_key_grip_t &grip);
/**
* @brief Remove subkey grip from key's list.
*
* @param key key pointer to the primary key
* @param grip subkey's grip.
*/
void pgp_key_remove_subkey_grip(pgp_key_t *key, const pgp_key_grip_t &grip);
/**
* @brief Get the pgp key's subkey grip
*

511
third_party/rnp/src/lib/rnp.cpp поставляемый
Просмотреть файл

@ -197,6 +197,11 @@ static const pgp_map_t hash_alg_map[] = {{PGP_HASH_MD5, RNP_ALGNAME_MD5},
{PGP_HASH_SM3, RNP_ALGNAME_SM3},
{PGP_HASH_CRC24, RNP_ALGNAME_CRC24}};
static const pgp_map_t s2k_type_map[] = {
{PGP_S2KS_SIMPLE, "Simple"},
{PGP_S2KS_SALTED, "Salted"},
{PGP_S2KS_ITERATED_AND_SALTED, "Iterated and salted"}};
static const pgp_bit_map_t key_usage_map[] = {{PGP_KF_SIGN, "sign"},
{PGP_KF_CERTIFY, "certify"},
{PGP_KF_ENCRYPT, "encrypt"},
@ -371,6 +376,43 @@ parse_ks_format(pgp_key_store_format_t *key_store_format, const char *format)
return true;
}
static rnp_result_t
hex_encode_value(const uint8_t *value, size_t len, char **res, rnp_hex_format_t format)
{
size_t hex_len = len * 2 + 1;
*res = (char *) malloc(hex_len);
if (!*res) {
return RNP_ERROR_OUT_OF_MEMORY;
}
if (!rnp_hex_encode(value, len, *res, hex_len, format)) {
free(*res);
*res = NULL;
return RNP_ERROR_GENERIC;
}
return RNP_SUCCESS;
}
static rnp_result_t
get_map_value(const pgp_map_t *map, size_t msize, int val, char **res)
{
const char *str = NULL;
for (size_t i = 0; i < msize; i++) {
if (map[i].type == val) {
str = map[i].string;
break;
}
}
if (!str) {
return RNP_ERROR_BAD_PARAMETERS;
}
char *strcp = strdup(str);
if (!strcp) {
return RNP_ERROR_OUT_OF_MEMORY;
}
*res = strcp;
return RNP_SUCCESS;
}
rnp_result_t
rnp_ffi_create(rnp_ffi_t *ffi, const char *pub_format, const char *sec_format)
{
@ -2665,6 +2707,102 @@ rnp_verify_dest_provider(pgp_parse_handler_t *handler,
return true;
}
static void
recipient_handle_from_pk_sesskey(rnp_recipient_handle_t handle,
const pgp_pk_sesskey_t &sesskey)
{
memcpy(handle->keyid, sesskey.key_id, PGP_KEY_ID_SIZE);
handle->palg = sesskey.alg;
}
static void
symenc_handle_from_sk_sesskey(rnp_symenc_handle_t handle, const pgp_sk_sesskey_t &sesskey)
{
handle->alg = sesskey.alg;
handle->halg = sesskey.s2k.hash_alg;
handle->s2k_type = sesskey.s2k.specifier;
if (sesskey.s2k.specifier == PGP_S2KS_ITERATED_AND_SALTED) {
handle->iterations = pgp_s2k_decode_iterations(sesskey.s2k.iterations);
} else {
handle->iterations = 1;
}
handle->aalg = sesskey.aalg;
}
static void
rnp_verify_on_recipients(const std::vector<pgp_pk_sesskey_t> &recipients,
const std::vector<pgp_sk_sesskey_t> &passwords,
void * param)
{
rnp_op_verify_t op = (rnp_op_verify_t) param;
if (!recipients.empty()) {
op->recipients =
(rnp_recipient_handle_t) calloc(recipients.size(), sizeof(*op->recipients));
if (!op->recipients) {
FFI_LOG(op->ffi, "allocation failed");
return;
}
for (size_t i = 0; i < recipients.size(); i++) {
recipient_handle_from_pk_sesskey(&op->recipients[i], recipients[i]);
}
}
op->recipient_count = recipients.size();
if (!passwords.empty()) {
op->symencs = (rnp_symenc_handle_t) calloc(passwords.size(), sizeof(*op->symencs));
if (!op->symencs) {
FFI_LOG(op->ffi, "allocation failed");
return;
}
for (size_t i = 0; i < passwords.size(); i++) {
symenc_handle_from_sk_sesskey(&op->symencs[i], passwords[i]);
}
}
op->symenc_count = passwords.size();
}
static void
rnp_verify_on_decryption_start(pgp_pk_sesskey_t *pubenc, pgp_sk_sesskey_t *symenc, void *param)
{
rnp_op_verify_t op = (rnp_op_verify_t) param;
if (pubenc) {
op->used_recipient = (rnp_recipient_handle_t) calloc(1, sizeof(*op->used_recipient));
if (!op->used_recipient) {
FFI_LOG(op->ffi, "allocation failed");
return;
}
recipient_handle_from_pk_sesskey(op->used_recipient, *pubenc);
return;
}
if (symenc) {
op->used_symenc = (rnp_symenc_handle_t) calloc(1, sizeof(*op->used_symenc));
if (!op->used_symenc) {
FFI_LOG(op->ffi, "allocation failed");
return;
}
symenc_handle_from_sk_sesskey(op->used_symenc, *symenc);
return;
}
FFI_LOG(op->ffi, "Warning! Both pubenc and symenc are NULL.");
}
static void
rnp_verify_on_decryption_info(bool mdc, pgp_aead_alg_t aead, pgp_symm_alg_t salg, void *param)
{
rnp_op_verify_t op = (rnp_op_verify_t) param;
op->mdc = mdc;
op->aead = aead;
op->salg = salg;
op->encrypted = true;
}
static void
rnp_verify_on_decryption_done(bool validated, void *param)
{
rnp_op_verify_t op = (rnp_op_verify_t) param;
op->validated = validated;
}
rnp_result_t
rnp_op_verify_create(rnp_op_verify_t *op,
rnp_ffi_t ffi,
@ -2721,6 +2859,10 @@ rnp_op_verify_execute(rnp_op_verify_t op)
handler.on_signatures = rnp_op_verify_on_signatures;
handler.src_provider = rnp_verify_src_provider;
handler.dest_provider = rnp_verify_dest_provider;
handler.on_recipients = rnp_verify_on_recipients;
handler.on_decryption_start = rnp_verify_on_decryption_start;
handler.on_decryption_info = rnp_verify_on_decryption_info;
handler.on_decryption_done = rnp_verify_on_decryption_done;
handler.param = op;
handler.ctx = &op->rnpctx;
@ -2773,6 +2915,196 @@ rnp_op_verify_get_file_info(rnp_op_verify_t op, char **filename, uint32_t *mtime
return RNP_SUCCESS;
}
static const char *
get_protection_mode(rnp_op_verify_t op)
{
if (!op->encrypted) {
return "none";
}
if (op->mdc) {
return "cfb-mdc";
}
if (op->aead == PGP_AEAD_NONE) {
return "cfb";
}
switch (op->aead) {
case PGP_AEAD_EAX:
return "aead-eax";
case PGP_AEAD_OCB:
return "aead-ocb";
default:
return "aead-unknown";
}
}
static const char *
get_protection_cipher(rnp_op_verify_t op)
{
if (!op->encrypted) {
return "none";
}
const char *str = "unknown";
ARRAY_LOOKUP_BY_ID(symm_alg_map, type, string, op->salg, str);
return str;
}
rnp_result_t
rnp_op_verify_get_protection_info(rnp_op_verify_t op, char **mode, char **cipher, bool *valid)
{
if (!op || (!mode && !cipher && !valid)) {
return RNP_ERROR_NULL_POINTER;
}
if (mode) {
*mode = strdup(get_protection_mode(op));
if (!*mode) {
return RNP_ERROR_OUT_OF_MEMORY;
}
}
if (cipher) {
*cipher = strdup(get_protection_cipher(op));
if (!*cipher) {
return RNP_ERROR_OUT_OF_MEMORY;
}
}
if (valid) {
*valid = op->validated;
}
return RNP_SUCCESS;
}
rnp_result_t
rnp_op_verify_get_recipient_count(rnp_op_verify_t op, size_t *count)
{
if (!op || !count) {
return RNP_ERROR_NULL_POINTER;
}
*count = op->recipient_count;
return RNP_SUCCESS;
}
rnp_result_t
rnp_op_verify_get_used_recipient(rnp_op_verify_t op, rnp_recipient_handle_t *recipient)
{
if (!op || !recipient) {
return RNP_ERROR_NULL_POINTER;
}
*recipient = op->used_recipient;
return RNP_SUCCESS;
}
rnp_result_t
rnp_op_verify_get_recipient_at(rnp_op_verify_t op,
size_t idx,
rnp_recipient_handle_t *recipient)
{
if (!op || !recipient) {
return RNP_ERROR_NULL_POINTER;
}
if (idx >= op->recipient_count) {
return RNP_ERROR_BAD_PARAMETERS;
}
*recipient = &op->recipients[idx];
return RNP_SUCCESS;
}
rnp_result_t
rnp_recipient_get_keyid(rnp_recipient_handle_t recipient, char **keyid)
{
if (!recipient || !keyid) {
return RNP_ERROR_NULL_POINTER;
}
return hex_encode_value(recipient->keyid, PGP_KEY_ID_SIZE, keyid, RNP_HEX_UPPERCASE);
}
rnp_result_t
rnp_recipient_get_alg(rnp_recipient_handle_t recipient, char **alg)
{
if (!recipient || !alg) {
return RNP_ERROR_NULL_POINTER;
}
return get_map_value(pubkey_alg_map, ARRAY_SIZE(pubkey_alg_map), recipient->palg, alg);
}
rnp_result_t
rnp_op_verify_get_symenc_count(rnp_op_verify_t op, size_t *count)
{
if (!op || !count) {
return RNP_ERROR_NULL_POINTER;
}
*count = op->symenc_count;
return RNP_SUCCESS;
}
rnp_result_t
rnp_op_verify_get_used_symenc(rnp_op_verify_t op, rnp_symenc_handle_t *symenc)
{
if (!op || !symenc) {
return RNP_ERROR_NULL_POINTER;
}
*symenc = op->used_symenc;
return RNP_SUCCESS;
}
rnp_result_t
rnp_op_verify_get_symenc_at(rnp_op_verify_t op, size_t idx, rnp_symenc_handle_t *symenc)
{
if (!op || !symenc) {
return RNP_ERROR_NULL_POINTER;
}
if (idx >= op->symenc_count) {
return RNP_ERROR_BAD_PARAMETERS;
}
*symenc = &op->symencs[idx];
return RNP_SUCCESS;
}
rnp_result_t
rnp_symenc_get_cipher(rnp_symenc_handle_t symenc, char **cipher)
{
if (!symenc || !cipher) {
return RNP_ERROR_NULL_POINTER;
}
return get_map_value(symm_alg_map, ARRAY_SIZE(symm_alg_map), symenc->alg, cipher);
}
rnp_result_t
rnp_symenc_get_aead_alg(rnp_symenc_handle_t symenc, char **alg)
{
if (!symenc || !alg) {
return RNP_ERROR_NULL_POINTER;
}
return get_map_value(aead_alg_map, ARRAY_SIZE(aead_alg_map), symenc->aalg, alg);
}
rnp_result_t
rnp_symenc_get_hash_alg(rnp_symenc_handle_t symenc, char **alg)
{
if (!symenc || !alg) {
return RNP_ERROR_NULL_POINTER;
}
return get_map_value(hash_alg_map, ARRAY_SIZE(hash_alg_map), symenc->halg, alg);
}
rnp_result_t
rnp_symenc_get_s2k_type(rnp_symenc_handle_t symenc, char **type)
{
if (!symenc || !type) {
return RNP_ERROR_NULL_POINTER;
}
return get_map_value(s2k_type_map, ARRAY_SIZE(s2k_type_map), symenc->s2k_type, type);
}
rnp_result_t
rnp_symenc_get_s2k_iterations(rnp_symenc_handle_t symenc, uint32_t *iterations)
{
if (!symenc || !iterations) {
return RNP_ERROR_NULL_POINTER;
}
*iterations = symenc->iterations;
return RNP_SUCCESS;
}
rnp_result_t
rnp_op_verify_destroy(rnp_op_verify_t op)
{
@ -2783,6 +3115,10 @@ rnp_op_verify_destroy(rnp_op_verify_t op)
}
free(op->signatures);
free(op->filename);
free(op->recipients);
free(op->used_recipient);
free(op->symencs);
free(op->used_symenc);
free(op);
}
return RNP_SUCCESS;
@ -2837,14 +3173,7 @@ rnp_op_verify_signature_get_hash(rnp_op_verify_signature_t sig, char **hash)
if (!sig || !hash) {
return RNP_ERROR_NULL_POINTER;
}
const char *hname = NULL;
ARRAY_LOOKUP_BY_ID(hash_alg_map, type, string, sig->sig_pkt.halg, hname);
if (hname) {
*hash = strdup(hname);
return RNP_SUCCESS;
}
return RNP_ERROR_BAD_STATE;
return get_map_value(hash_alg_map, ARRAY_SIZE(hash_alg_map), sig->sig_pkt.halg, hash);
}
rnp_result_t
@ -3335,28 +3664,50 @@ rnp_key_remove(rnp_key_handle_t key, uint32_t flags)
if (!key || !key->ffi) {
return RNP_ERROR_NULL_POINTER;
}
if (flags == 0) {
bool pub = false;
if (flags & RNP_KEY_REMOVE_PUBLIC) {
pub = true;
flags &= ~RNP_KEY_REMOVE_PUBLIC;
}
bool sec = false;
if (flags & RNP_KEY_REMOVE_SECRET) {
sec = true;
flags &= ~RNP_KEY_REMOVE_SECRET;
}
bool sub = false;
if (flags & RNP_KEY_REMOVE_SUBKEYS) {
sub = true;
flags &= ~RNP_KEY_REMOVE_SUBKEYS;
}
if (flags) {
FFI_LOG(key->ffi, "Unknown flags: %" PRIu32, flags);
return RNP_ERROR_BAD_PARAMETERS;
}
if (flags & RNP_KEY_REMOVE_PUBLIC) {
if (!pub && !sec) {
return RNP_ERROR_BAD_PARAMETERS;
}
if (sub && pgp_key_is_subkey(get_key_prefer_public(key))) {
return RNP_ERROR_BAD_PARAMETERS;
}
if (pub) {
if (!key->ffi->pubring || !key->pub) {
return RNP_ERROR_BAD_PARAMETERS;
}
if (!rnp_key_store_remove_key(key->ffi->pubring, key->pub)) {
if (!rnp_key_store_remove_key(key->ffi->pubring, key->pub, sub)) {
return RNP_ERROR_KEY_NOT_FOUND;
}
key->pub = NULL;
}
if (flags & RNP_KEY_REMOVE_SECRET) {
if (sec) {
if (!key->ffi->secring || !key->sec) {
return RNP_ERROR_BAD_PARAMETERS;
}
if (!rnp_key_store_remove_key(key->ffi->secring, key->sec)) {
if (!rnp_key_store_remove_key(key->ffi->secring, key->sec, sub)) {
return RNP_ERROR_KEY_NOT_FOUND;
}
key->sec = NULL;
}
return RNP_SUCCESS;
}
@ -4688,11 +5039,11 @@ done:
op->password = NULL;
}
if (ret && op->gen_pub) {
rnp_key_store_remove_key(op->ffi->pubring, op->gen_pub);
rnp_key_store_remove_key(op->ffi->pubring, op->gen_pub, false);
op->gen_pub = NULL;
}
if (ret && op->gen_sec) {
rnp_key_store_remove_key(op->ffi->secring, op->gen_sec);
rnp_key_store_remove_key(op->ffi->secring, op->gen_sec, false);
op->gen_sec = NULL;
}
return ret;
@ -5048,18 +5399,8 @@ rnp_signature_get_alg(rnp_signature_handle_t handle, char **alg)
if (!handle->sig) {
return RNP_ERROR_BAD_PARAMETERS;
}
const char *str = NULL;
ARRAY_LOOKUP_BY_ID(pubkey_alg_map, type, string, handle->sig->sig.palg, str);
if (!str) {
return RNP_ERROR_BAD_PARAMETERS;
}
char *algcp = strdup(str);
if (!algcp) {
return RNP_ERROR_OUT_OF_MEMORY;
}
*alg = algcp;
return RNP_SUCCESS;
return get_map_value(
pubkey_alg_map, ARRAY_SIZE(pubkey_alg_map), handle->sig->sig.palg, alg);
}
rnp_result_t
@ -5071,18 +5412,7 @@ rnp_signature_get_hash_alg(rnp_signature_handle_t handle, char **alg)
if (!handle->sig) {
return RNP_ERROR_BAD_PARAMETERS;
}
const char *str = NULL;
ARRAY_LOOKUP_BY_ID(hash_alg_map, type, string, handle->sig->sig.halg, str);
if (!str) {
return RNP_ERROR_BAD_PARAMETERS;
}
char *algcp = strdup(str);
if (!algcp) {
return RNP_ERROR_OUT_OF_MEMORY;
}
*alg = algcp;
return RNP_SUCCESS;
return get_map_value(hash_alg_map, ARRAY_SIZE(hash_alg_map), handle->sig->sig.halg, alg);
}
rnp_result_t
@ -5113,18 +5443,7 @@ rnp_signature_get_keyid(rnp_signature_handle_t handle, char **result)
return RNP_SUCCESS;
}
size_t hex_len = PGP_KEY_ID_SIZE * 2 + 1;
*result = (char *) malloc(hex_len);
if (!*result) {
return RNP_ERROR_OUT_OF_MEMORY;
}
if (!rnp_hex_encode(keyid, PGP_KEY_ID_SIZE, *result, hex_len, RNP_HEX_UPPERCASE)) {
free(*result);
*result = NULL;
return RNP_ERROR_GENERIC;
}
return RNP_SUCCESS;
return hex_encode_value(keyid, PGP_KEY_ID_SIZE, result, RNP_HEX_UPPERCASE);
}
rnp_result_t
@ -5243,21 +5562,9 @@ rnp_key_get_alg(rnp_key_handle_t handle, char **alg)
if (!handle || !alg) {
return RNP_ERROR_NULL_POINTER;
}
pgp_key_t * key = get_key_prefer_public(handle);
const char *str = NULL;
ARRAY_LOOKUP_BY_ID(pubkey_alg_map, type, string, pgp_key_get_alg(key), str);
if (!str) {
return RNP_ERROR_BAD_PARAMETERS;
}
char *algcp = strdup(str);
if (!algcp) {
return RNP_ERROR_OUT_OF_MEMORY;
}
*alg = algcp;
return RNP_SUCCESS;
pgp_key_t *key = get_key_prefer_public(handle);
return get_map_value(
pubkey_alg_map, ARRAY_SIZE(pubkey_alg_map), pgp_key_get_alg(key), alg);
}
rnp_result_t
@ -5316,70 +5623,40 @@ rnp_key_get_curve(rnp_key_handle_t handle, char **curve)
rnp_result_t
rnp_key_get_fprint(rnp_key_handle_t handle, char **fprint)
{
if (handle == NULL || fprint == NULL)
if (!handle || !fprint) {
return RNP_ERROR_NULL_POINTER;
size_t hex_len = PGP_FINGERPRINT_HEX_SIZE + 1;
*fprint = (char *) malloc(hex_len);
if (*fprint == NULL)
return RNP_ERROR_OUT_OF_MEMORY;
pgp_key_t *key = get_key_prefer_public(handle);
if (!rnp_hex_encode(pgp_key_get_fp(key)->fingerprint,
pgp_key_get_fp(key)->length,
*fprint,
hex_len,
RNP_HEX_UPPERCASE)) {
return RNP_ERROR_GENERIC;
}
return RNP_SUCCESS;
const pgp_fingerprint_t *fp = pgp_key_get_fp(get_key_prefer_public(handle));
return hex_encode_value(fp->fingerprint, fp->length, fprint, RNP_HEX_UPPERCASE);
}
rnp_result_t
rnp_key_get_keyid(rnp_key_handle_t handle, char **keyid)
{
if (handle == NULL || keyid == NULL)
if (!handle || !keyid) {
return RNP_ERROR_NULL_POINTER;
size_t hex_len = PGP_KEY_ID_SIZE * 2 + 1;
*keyid = (char *) malloc(hex_len);
if (*keyid == NULL)
return RNP_ERROR_OUT_OF_MEMORY;
}
pgp_key_t *key = get_key_prefer_public(handle);
if (!rnp_hex_encode(
pgp_key_get_keyid(key), PGP_KEY_ID_SIZE, *keyid, hex_len, RNP_HEX_UPPERCASE)) {
return RNP_ERROR_GENERIC;
}
return RNP_SUCCESS;
return hex_encode_value(pgp_key_get_keyid(key), PGP_KEY_ID_SIZE, keyid, RNP_HEX_UPPERCASE);
}
rnp_result_t
rnp_key_get_grip(rnp_key_handle_t handle, char **grip)
{
if (handle == NULL || grip == NULL)
if (!handle || !grip) {
return RNP_ERROR_NULL_POINTER;
size_t hex_len = PGP_KEY_GRIP_SIZE * 2 + 1;
*grip = (char *) malloc(hex_len);
if (*grip == NULL)
return RNP_ERROR_OUT_OF_MEMORY;
pgp_key_t *key = get_key_prefer_public(handle);
if (!rnp_hex_encode(pgp_key_get_grip(key).data(),
pgp_key_get_grip(key).size(),
*grip,
hex_len,
RNP_HEX_UPPERCASE)) {
return RNP_ERROR_GENERIC;
}
return RNP_SUCCESS;
const pgp_key_grip_t &kgrip = pgp_key_get_grip(get_key_prefer_public(handle));
return hex_encode_value(kgrip.data(), kgrip.size(), grip, RNP_HEX_UPPERCASE);
}
rnp_result_t
rnp_key_get_primary_grip(rnp_key_handle_t handle, char **grip)
{
if (handle == NULL || grip == NULL) {
if (!handle || !grip) {
return RNP_ERROR_NULL_POINTER;
}
@ -5391,20 +5668,8 @@ rnp_key_get_primary_grip(rnp_key_handle_t handle, char **grip)
*grip = NULL;
return RNP_SUCCESS;
}
size_t hex_len = PGP_KEY_GRIP_SIZE * 2 + 1;
*grip = (char *) malloc(hex_len);
if (*grip == NULL) {
return RNP_ERROR_OUT_OF_MEMORY;
}
if (!rnp_hex_encode(pgp_key_get_primary_grip(key).data(),
pgp_key_get_primary_grip(key).size(),
*grip,
hex_len,
RNP_HEX_UPPERCASE)) {
free(*grip);
return RNP_ERROR_GENERIC;
}
return RNP_SUCCESS;
const pgp_key_grip_t &pgrip = pgp_key_get_primary_grip(key);
return hex_encode_value(pgrip.data(), pgrip.size(), grip, RNP_HEX_UPPERCASE);
}
rnp_result_t

6
third_party/rnp/src/lib/utils.h поставляемый
Просмотреть файл

@ -207,12 +207,6 @@ STORE64BE(uint8_t x[8], uint64_t y)
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
/* Macro _GLIBCXX_USE_CXX11_ABI was first introduced with GCC 5.0, which
* we assume to be bundled with a sane implementation of std::regex. */
#if !defined(__GNUC__) || defined(_GLIBCXX_USE_CXX11_ABI)
#define RNP_USE_STD_REGEX 1
#endif
inline char *
getenv_logname(void)
{

4
third_party/rnp/src/lib/version.h поставляемый
Просмотреть файл

@ -28,9 +28,9 @@
#define RNP_VERSION_PATCH 1
#define RNP_VERSION_STRING "0.13.1"
#define RNP_VERSION_STRING_FULL "0.13.1+git20200609.b9335cee.MZLA"
#define RNP_VERSION_STRING_FULL "0.13.1+git20200619.ac070578.MZLA"
#define RNP_VERSION_COMMIT_TIMESTAMP 1591722904
#define RNP_VERSION_COMMIT_TIMESTAMP 1592576776
// using a 32-bit version with 10 bits per component
#define RNP_VERSION_COMPONENT_MASK 0x3ff

Просмотреть файл

@ -188,7 +188,7 @@ rnp_key_store_add_transferable_key(rnp_key_store_t *keyring, pgp_transferable_ke
return true;
error:
/* during key addition all fields are copied so will be cleaned below */
rnp_key_store_remove_key(keyring, addkey);
rnp_key_store_remove_key(keyring, addkey, false);
return false;
}

Просмотреть файл

@ -40,6 +40,7 @@
#include <dirent.h>
#include <errno.h>
#include <algorithm>
#include <stdexcept>
#include <rnp/rnp_sdk.h>
#include <rekey/rnp_key_store.h>
@ -676,15 +677,40 @@ rnp_key_store_import_signature(rnp_key_store_t * keyring,
}
bool
rnp_key_store_remove_key(rnp_key_store_t *keyring, const pgp_key_t *key)
rnp_key_store_remove_key(rnp_key_store_t *keyring, const pgp_key_t *key, bool subkeys)
{
keyring->keybygrip.erase(pgp_key_get_grip(key));
size_t oldsize = keyring->keys.size();
keyring->keys.erase(std::remove_if(keyring->keys.begin(),
keyring->keys.end(),
[key](pgp_key_t &_key) { return key == &_key; }));
auto it = keyring->keybygrip.find(pgp_key_get_grip(key));
if (it == keyring->keybygrip.end()) {
return false;
}
return oldsize != keyring->keys.size();
/* cleanup primary_grip (or subkey)/subkey_grips */
if (pgp_key_is_primary_key(key) && pgp_key_get_subkey_count(key)) {
for (size_t i = 0; i < pgp_key_get_subkey_count(key); i++) {
auto it = keyring->keybygrip.find(pgp_key_get_subkey_grip(key, i));
if (it == keyring->keybygrip.end()) {
continue;
}
/* if subkeys are deleted then no need to update grips */
if (subkeys) {
keyring->keys.erase(it->second);
keyring->keybygrip.erase(it);
continue;
}
it->second->primary_grip = {};
it->second->primary_grip_set = false;
}
}
if (pgp_key_is_subkey(key) && pgp_key_has_primary_grip(key)) {
pgp_key_t *primary = rnp_key_store_get_primary_key(keyring, key);
if (primary) {
pgp_key_remove_subkey_grip(primary, pgp_key_get_grip(key));
}
}
keyring->keys.erase(it->second);
keyring->keybygrip.erase(it);
return true;
}
/**
@ -731,12 +757,11 @@ rnp_key_store_get_key_by_id(rnp_key_store_t *keyring, const uint8_t *keyid, pgp_
const pgp_key_t *
rnp_key_store_get_key_by_grip(const rnp_key_store_t *keyring, const pgp_key_grip_t &grip)
{
try {
return &*keyring->keybygrip.at(grip);
} catch (const std::exception &e) {
RNP_LOG("%s", e.what());
auto it = keyring->keybygrip.find(grip);
if (it == keyring->keybygrip.end()) {
return NULL;
}
return &*it->second;
}
pgp_key_t *

207
third_party/rnp/src/librepgp/stream-parse.cpp поставляемый
Просмотреть файл

@ -82,41 +82,43 @@ typedef struct pgp_source_packet_param_t {
} pgp_source_packet_param_t;
typedef struct pgp_source_encrypted_param_t {
pgp_source_packet_param_t pkt; /* underlying packet-related params */
list symencs; /* array of sym-encrypted session keys */
list pubencs; /* array of pk-encrypted session keys */
bool has_mdc; /* encrypted with mdc, i.e. tag 18 */
bool mdc_validated; /* mdc was validated already */
bool aead; /* AEAD encrypted data packet, tag 20 */
bool aead_validated; /* we read and validated last chunk */
pgp_crypt_t decrypt; /* decrypting crypto */
pgp_hash_t mdc; /* mdc SHA1 hash */
size_t chunklen; /* size of AEAD chunk in bytes */
size_t chunkin; /* number of bytes read from the current chunk */
size_t chunkidx; /* index of the current chunk */
uint8_t cache[PGP_AEAD_CACHE_LEN]; /* read cache */
size_t cachelen; /* number of bytes in the cache */
size_t cachepos; /* index of first unread byte in the cache */
pgp_aead_hdr_t aead_hdr; /* AEAD encryption parameters */
uint8_t aead_ad[PGP_AEAD_MAX_AD_LEN]; /* additional data */
size_t aead_adlen; /* length of the additional data */
pgp_source_packet_param_t pkt; /* underlying packet-related params */
std::vector<pgp_sk_sesskey_t> symencs; /* array of sym-encrypted session keys */
std::vector<pgp_pk_sesskey_t> pubencs; /* array of pk-encrypted session keys */
bool has_mdc; /* encrypted with mdc, i.e. tag 18 */
bool mdc_validated; /* mdc was validated already */
bool aead; /* AEAD encrypted data packet, tag 20 */
bool aead_validated; /* we read and validated last chunk */
pgp_crypt_t decrypt; /* decrypting crypto */
pgp_hash_t mdc; /* mdc SHA1 hash */
size_t chunklen; /* size of AEAD chunk in bytes */
size_t chunkin; /* number of bytes read from the current chunk */
size_t chunkidx; /* index of the current chunk */
uint8_t cache[PGP_AEAD_CACHE_LEN]; /* read cache */
size_t cachelen; /* number of bytes in the cache */
size_t cachepos; /* index of first unread byte in the cache */
pgp_aead_hdr_t aead_hdr; /* AEAD encryption parameters */
uint8_t aead_ad[PGP_AEAD_MAX_AD_LEN]; /* additional data */
size_t aead_adlen; /* length of the additional data */
pgp_symm_alg_t salg; /* data encryption algorithm */
pgp_parse_handler_t * handler; /* parsing handler with callbacks */
} pgp_source_encrypted_param_t;
typedef struct pgp_source_signed_param_t {
pgp_processing_ctx_t *ctx; /* processing context */
pgp_source_t * readsrc; /* source to read from */
bool detached; /* detached signature */
bool cleartext; /* source is cleartext signed */
bool clr_eod; /* cleartext data is over */
bool clr_fline; /* first line of the cleartext */
bool clr_mline; /* in the middle of the very long line */
uint8_t out[CT_BUF_LEN]; /* cleartext output cache for easier parsing */
size_t outlen; /* total bytes in out */
size_t outpos; /* offset of first available byte in out */
list onepasses; /* list of one-pass singatures */
list sigs; /* list of signatures */
list hashes; /* hash contexts */
list siginfos; /* signature validation info */
pgp_parse_handler_t *handler; /* parsing handler with callbacks */
pgp_source_t * readsrc; /* source to read from */
bool detached; /* detached signature */
bool cleartext; /* source is cleartext signed */
bool clr_eod; /* cleartext data is over */
bool clr_fline; /* first line of the cleartext */
bool clr_mline; /* in the middle of the very long line */
uint8_t out[CT_BUF_LEN]; /* cleartext output cache for easier parsing */
size_t outlen; /* total bytes in out */
size_t outpos; /* offset of first available byte in out */
list onepasses; /* list of one-pass singatures */
list sigs; /* list of signatures */
list hashes; /* hash contexts */
list siginfos; /* signature validation info */
} pgp_source_signed_param_t;
typedef struct pgp_source_compressed_param_t {
@ -686,6 +688,13 @@ encrypted_src_finish(pgp_source_t *src)
{
pgp_source_encrypted_param_t *param = (pgp_source_encrypted_param_t *) src->param;
/* report to the handler that decryption is finished */
if (param->handler->on_decryption_done) {
bool validated =
(param->has_mdc && param->mdc_validated) || (param->aead && param->aead_validated);
param->handler->on_decryption_done(validated, param->handler->param);
}
if (param->aead) {
if (!param->aead_validated) {
RNP_LOG("aead last chunk was not validated");
@ -710,8 +719,9 @@ encrypted_src_close(pgp_source_t *src)
return;
}
list_destroy(&param->symencs);
list_destroy(&param->pubencs);
/* to be removed once pgp_source_t is migrated to C++ */
param->symencs.~vector();
param->pubencs.~vector();
if (param->pkt.partial) {
src_close(param->pkt.readsrc);
@ -930,10 +940,10 @@ signed_src_finish(pgp_source_t *src)
}
/* Get the public key */
if (!(key = pgp_request_key(param->ctx->handler.key_provider, &keyctx))) {
if (!(key = pgp_request_key(param->handler->key_provider, &keyctx))) {
// fallback to secret key
keyctx.secret = true;
if (!(key = pgp_request_key(param->ctx->handler.key_provider, &keyctx))) {
if (!(key = pgp_request_key(param->handler->key_provider, &keyctx))) {
RNP_LOG("signer's key not found");
sinfo->no_signer = true;
continue;
@ -950,7 +960,7 @@ signed_src_finish(pgp_source_t *src)
sinfo = (pgp_signature_info_t *) si;
sinfos[sinfoc++] = *sinfo;
if (sinfo->no_signer && param->ctx->handler.ctx->discard) {
if (sinfo->no_signer && param->handler->ctx->discard) {
/* if output is discarded then we interested in verification */
ret = RNP_ERROR_SIGNATURE_INVALID;
continue;
@ -962,8 +972,8 @@ signed_src_finish(pgp_source_t *src)
}
/* call the callback with signature infos */
if (param->ctx->handler.on_signatures) {
param->ctx->handler.on_signatures(sinfos, sinfoc, param->ctx->handler.param);
if (param->handler->on_signatures) {
param->handler->on_signatures(sinfos, sinfoc, param->handler->param);
}
free(sinfos);
@ -1365,7 +1375,9 @@ encrypted_try_key(pgp_source_encrypted_param_t *param,
/* Start AEAD decrypting, assuming we have correct key */
res = encrypted_start_aead(param, salg, &decbuf[1]);
}
if (res) {
param->salg = salg;
}
finish:
pgp_forget(&checksum, sizeof(checksum));
pgp_forget(decbuf, sizeof(decbuf));
@ -1400,35 +1412,33 @@ encrypted_try_password(pgp_source_encrypted_param_t *param, const char *password
bool decres;
int res;
for (list_item *se = list_front(param->symencs); se; se = list_next(se)) {
for (auto &skey : param->symencs) {
/* deriving symmetric key from password */
pgp_sk_sesskey_t *skey = (pgp_sk_sesskey_t *) se;
keysize = pgp_key_size(skey->alg);
if (!keysize || !pgp_s2k_derive_key(&skey->s2k, password, keybuf, keysize)) {
keysize = pgp_key_size(skey.alg);
if (!keysize || !pgp_s2k_derive_key(&skey.s2k, password, keybuf, keysize)) {
continue;
}
RNP_DHEX("derived key: ", keybuf, keysize);
if (skey->version == PGP_SKSK_V4) {
if (skey.version == PGP_SKSK_V4) {
/* v4 symmetrically-encrypted session key */
if (skey->enckeylen > 0) {
if (skey.enckeylen > 0) {
/* decrypting session key */
if (!pgp_cipher_cfb_start(&crypt, skey->alg, keybuf, NULL)) {
if (!pgp_cipher_cfb_start(&crypt, skey.alg, keybuf, NULL)) {
continue;
}
pgp_cipher_cfb_decrypt(&crypt, keybuf, skey->enckey, skey->enckeylen);
pgp_cipher_cfb_decrypt(&crypt, keybuf, skey.enckey, skey.enckeylen);
pgp_cipher_cfb_finish(&crypt);
alg = (pgp_symm_alg_t) keybuf[0];
keysize = pgp_key_size(alg);
if (!keysize || (keysize + 1 != skey->enckeylen)) {
if (!keysize || (keysize + 1 != skey.enckeylen)) {
continue;
}
memmove(keybuf, keybuf + 1, keysize);
} else {
alg = (pgp_symm_alg_t) skey->alg;
alg = (pgp_symm_alg_t) skey.alg;
}
if (!pgp_block_size(alg)) {
@ -1436,37 +1446,37 @@ encrypted_try_password(pgp_source_encrypted_param_t *param, const char *password
}
keyavail = true;
} else if (skey->version == PGP_SKSK_V5) {
} else if (skey.version == PGP_SKSK_V5) {
/* v5 AEAD-encrypted session key */
size_t taglen = pgp_cipher_aead_tag_len(skey->aalg);
size_t taglen = pgp_cipher_aead_tag_len(skey.aalg);
size_t noncelen;
if (!taglen || (keysize != skey->enckeylen - taglen)) {
if (!taglen || (keysize != skey.enckeylen - taglen)) {
continue;
}
alg = skey->alg;
alg = skey.alg;
/* initialize cipher */
if (!pgp_cipher_aead_init(&crypt, skey->alg, skey->aalg, keybuf, true)) {
if (!pgp_cipher_aead_init(&crypt, skey.alg, skey.aalg, keybuf, true)) {
continue;
}
/* set additional data */
if (!encrypted_sesk_set_ad(&crypt, skey)) {
if (!encrypted_sesk_set_ad(&crypt, &skey)) {
RNP_LOG("failed to set ad");
continue;
}
/* calculate nonce */
noncelen = pgp_cipher_aead_nonce(skey->aalg, skey->iv, nonce, 0);
noncelen = pgp_cipher_aead_nonce(skey.aalg, skey.iv, nonce, 0);
RNP_DHEX("nonce: ", nonce, noncelen);
RNP_DHEX("encrypted key: ", skey->enckey, skey->enckeylen);
RNP_DHEX("encrypted key: ", skey.enckey, skey.enckeylen);
/* start cipher, decrypt key and verify tag */
keyavail = pgp_cipher_aead_start(&crypt, nonce, noncelen);
decres = keyavail &&
pgp_cipher_aead_finish(&crypt, keybuf, skey->enckey, skey->enckeylen);
decres =
keyavail && pgp_cipher_aead_finish(&crypt, keybuf, skey.enckey, skey.enckeylen);
if (decres) {
RNP_DHEX("decrypted key: ", keybuf, pgp_key_size(param->aead_hdr.ealg));
@ -1490,7 +1500,12 @@ encrypted_try_password(pgp_source_encrypted_param_t *param, const char *password
continue;
}
param->salg = param->aead ? param->aead_hdr.ealg : alg;
res = 1;
/* inform handler that we used this symenc */
if (param->handler->on_decryption_start) {
param->handler->on_decryption_start(NULL, &skey, param->handler->param);
}
goto finish;
}
@ -1774,16 +1789,20 @@ encrypted_read_packet_data(pgp_source_encrypted_param_t *param)
if ((errcode = stream_parse_sk_sesskey(param->pkt.readsrc, &skey))) {
return errcode;
}
if (!list_append(&param->symencs, &skey, sizeof(skey))) {
try {
param->symencs.push_back(skey);
} catch (const std::exception &e) {
RNP_LOG("%s", e.what());
return RNP_ERROR_OUT_OF_MEMORY;
}
} else if (ptype == PGP_PKT_PK_SESSION_KEY) {
if ((errcode = stream_parse_pk_sesskey(param->pkt.readsrc, &pkey))) {
return errcode;
}
if (!list_append(&param->pubencs, &pkey, sizeof(pkey))) {
try {
param->pubencs.push_back(pkey);
} catch (const std::exception &e) {
RNP_LOG("%s", e.what());
return RNP_ERROR_OUT_OF_MEMORY;
}
} else if ((ptype == PGP_PKT_SE_DATA) || (ptype == PGP_PKT_SE_IP_DATA) ||
@ -1849,12 +1868,11 @@ encrypted_read_packet_data(pgp_source_encrypted_param_t *param)
}
static rnp_result_t
init_encrypted_src(pgp_processing_ctx_t *ctx, pgp_source_t *src, pgp_source_t *readsrc)
init_encrypted_src(pgp_parse_handler_t *handler, pgp_source_t *src, pgp_source_t *readsrc)
{
rnp_result_t errcode = RNP_ERROR_GENERIC;
pgp_source_encrypted_param_t *param;
pgp_key_t * seckey = NULL;
pgp_key_request_ctx_t keyctx;
pgp_key_pkt_t * decrypted_seckey = NULL;
char password[MAX_PASSWORD_LENGTH] = {0};
int intres;
@ -1865,6 +1883,7 @@ init_encrypted_src(pgp_processing_ctx_t *ctx, pgp_source_t *src, pgp_source_t *r
}
param = (pgp_source_encrypted_param_t *) src->param;
param->pkt.readsrc = readsrc;
param->handler = handler;
src->close = encrypted_src_close;
src->finish = encrypted_src_finish;
@ -1881,30 +1900,34 @@ init_encrypted_src(pgp_processing_ctx_t *ctx, pgp_source_t *src, pgp_source_t *r
/* Obtaining the symmetric key */
have_key = false;
if (!ctx->handler.password_provider) {
if (!handler->password_provider) {
RNP_LOG("no password provider");
errcode = RNP_ERROR_BAD_PARAMETERS;
goto finish;
}
/* informing handler about the available pubencs/symencs */
if (handler->on_recipients) {
handler->on_recipients(param->pubencs, param->symencs, handler->param);
}
/* Trying public-key decryption */
if (list_length(param->pubencs) > 0) {
if (!ctx->handler.key_provider) {
if (!param->pubencs.empty()) {
if (!handler->key_provider) {
RNP_LOG("no key provider");
errcode = RNP_ERROR_BAD_PARAMETERS;
goto finish;
}
pgp_key_request_ctx_t keyctx = {};
keyctx.op = PGP_OP_DECRYPT_SYM;
keyctx.secret = true;
keyctx.search.type = PGP_KEY_SEARCH_KEYID;
for (list_item *pe = list_front(param->pubencs); pe; pe = list_next(pe)) {
memcpy(keyctx.search.by.keyid,
((pgp_pk_sesskey_t *) pe)->key_id,
sizeof(keyctx.search.by.keyid));
for (auto &pubenc : param->pubencs) {
memcpy(keyctx.search.by.keyid, pubenc.key_id, sizeof(keyctx.search.by.keyid));
/* Get the key if any */
if (!(seckey = pgp_request_key(ctx->handler.key_provider, &keyctx))) {
if (!(seckey = pgp_request_key(handler->key_provider, &keyctx))) {
errcode = RNP_ERROR_NO_SUITABLE_KEY;
continue;
}
@ -1912,7 +1935,7 @@ init_encrypted_src(pgp_processing_ctx_t *ctx, pgp_source_t *src, pgp_source_t *r
if (pgp_key_is_encrypted(seckey)) {
pgp_password_ctx_t pass_ctx{.op = PGP_OP_DECRYPT, .key = seckey};
decrypted_seckey =
pgp_decrypt_seckey(seckey, ctx->handler.password_provider, &pass_ctx);
pgp_decrypt_seckey(seckey, handler->password_provider, &pass_ctx);
if (!decrypted_seckey) {
errcode = RNP_ERROR_BAD_PASSWORD;
continue;
@ -1922,11 +1945,13 @@ init_encrypted_src(pgp_processing_ctx_t *ctx, pgp_source_t *src, pgp_source_t *r
}
/* Try to initialize the decryption */
if (encrypted_try_key(param,
(pgp_pk_sesskey_t *) pe,
decrypted_seckey,
rnp_ctx_rng_handle(ctx->handler.ctx))) {
if (encrypted_try_key(
param, &pubenc, decrypted_seckey, rnp_ctx_rng_handle(handler->ctx))) {
have_key = true;
/* inform handler that we used this pubenc */
if (handler->on_decryption_start) {
handler->on_decryption_start(&pubenc, NULL, handler->param);
}
}
/* Destroy decrypted key */
@ -1943,10 +1968,10 @@ init_encrypted_src(pgp_processing_ctx_t *ctx, pgp_source_t *src, pgp_source_t *r
}
/* Trying password-based decryption */
if (!have_key && (list_length(param->symencs) > 0)) {
if (!have_key && !param->symencs.empty()) {
pgp_password_ctx_t pass_ctx{.op = PGP_OP_DECRYPT_SYM, .key = NULL};
if (!pgp_request_password(
ctx->handler.password_provider, &pass_ctx, password, sizeof(password))) {
handler->password_provider, &pass_ctx, password, sizeof(password))) {
errcode = RNP_ERROR_BAD_PASSWORD;
goto finish;
}
@ -1969,13 +1994,17 @@ init_encrypted_src(pgp_processing_ctx_t *ctx, pgp_source_t *src, pgp_source_t *r
goto finish;
}
/* report decryption start to the handler */
if (handler->on_decryption_info) {
handler->on_decryption_info(
param->has_mdc, param->aead_hdr.aalg, param->salg, handler->param);
}
errcode = RNP_SUCCESS;
finish:
if (errcode != RNP_SUCCESS) {
src_close(src);
}
pgp_forget(password, sizeof(password));
return errcode;
}
@ -2014,7 +2043,7 @@ init_cleartext_signed_src(pgp_source_t *src)
}
static rnp_result_t
init_signed_src(pgp_processing_ctx_t *ctx, pgp_source_t *src, pgp_source_t *readsrc)
init_signed_src(pgp_parse_handler_t *handler, pgp_source_t *src, pgp_source_t *readsrc)
{
rnp_result_t errcode = RNP_ERROR_GENERIC;
pgp_source_signed_param_t *param;
@ -2032,7 +2061,7 @@ init_signed_src(pgp_processing_ctx_t *ctx, pgp_source_t *src, pgp_source_t *read
param = (pgp_source_signed_param_t *) src->param;
param->readsrc = readsrc;
param->ctx = ctx;
param->handler = handler;
param->cleartext = cleartext;
src->read = cleartext ? cleartext_src_read : signed_src_read;
src->close = signed_src_close;
@ -2040,7 +2069,7 @@ init_signed_src(pgp_processing_ctx_t *ctx, pgp_source_t *src, pgp_source_t *read
src->type = cleartext ? PGP_STREAM_CLEARTEXT : PGP_STREAM_SIGNED;
/* we need key provider to validate signatures */
if (!ctx->handler.key_provider) {
if (!handler->key_provider) {
RNP_LOG("no key provider");
errcode = RNP_ERROR_BAD_PARAMETERS;
goto finish;
@ -2163,11 +2192,11 @@ init_packet_sequence(pgp_processing_ctx_t *ctx, pgp_source_t *src)
switch (type) {
case PGP_PKT_PK_SESSION_KEY:
case PGP_PKT_SK_SESSION_KEY:
ret = init_encrypted_src(ctx, &psrc, lsrc);
ret = init_encrypted_src(&ctx->handler, &psrc, lsrc);
break;
case PGP_PKT_ONE_PASS_SIG:
case PGP_PKT_SIGNATURE:
ret = init_signed_src(ctx, &psrc, lsrc);
ret = init_signed_src(&ctx->handler, &psrc, lsrc);
break;
case PGP_PKT_COMPRESSED:
ret = init_compressed_src(&psrc, lsrc);
@ -2217,7 +2246,7 @@ init_cleartext_sequence(pgp_processing_ctx_t *ctx, pgp_source_t *src)
pgp_source_t clrsrc = {0};
rnp_result_t res;
if ((res = init_signed_src(ctx, &clrsrc, src))) {
if ((res = init_signed_src(&ctx->handler, &clrsrc, src))) {
return res;
}

18
third_party/rnp/src/librepgp/stream-parse.h поставляемый
Просмотреть файл

@ -43,6 +43,18 @@ typedef bool pgp_destination_func_t(pgp_parse_handler_t *
typedef bool pgp_source_func_t(pgp_parse_handler_t *handler, pgp_source_t *src);
typedef void pgp_signatures_func_t(pgp_signature_info_t *sigs, int count, void *param);
typedef void pgp_on_recipients_func_t(const std::vector<pgp_pk_sesskey_t> &recipients,
const std::vector<pgp_sk_sesskey_t> &passwords,
void * param);
typedef void pgp_decryption_start_func_t(pgp_pk_sesskey_t *pubenc,
pgp_sk_sesskey_t *symenc,
void * param);
typedef void pgp_decryption_info_func_t(bool mdc,
pgp_aead_alg_t aead,
pgp_symm_alg_t salg,
void * param);
typedef void pgp_decryption_done_func_t(bool validated, void *param);
/* handler used to return needed information during pgp source processing */
typedef struct pgp_parse_handler_t {
pgp_password_provider_t *password_provider; /* if NULL then default will be used */
@ -52,7 +64,11 @@ typedef struct pgp_parse_handler_t {
pgp_destination_func_t *dest_provider; /* called when destination stream is required */
pgp_source_func_t * src_provider; /* required to provider source during the detached
signature verification */
pgp_signatures_func_t *on_signatures; /* for signature verification results */
pgp_on_recipients_func_t * on_recipients; /* called before decryption start */
pgp_decryption_start_func_t *on_decryption_start; /* called when decryption key obtained */
pgp_decryption_info_func_t * on_decryption_info; /* called when decryption is started */
pgp_decryption_done_func_t * on_decryption_done; /* called when decryption is finished */
pgp_signatures_func_t * on_signatures; /* for signature verification results */
rnp_ctx_t *ctx; /* operation context */
void * param; /* additional parameters */

4
third_party/rnp/src/rnp/CMakeLists.txt поставляемый
Просмотреть файл

@ -40,6 +40,10 @@ target_link_libraries(rnp
JSON-C::JSON-C
)
if (WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_link_libraries(rnp PRIVATE regex)
endif()
include(GNUInstallDirs)
install(TARGETS rnp
RUNTIME

1
third_party/rnp/src/rnp/fficli.cpp поставляемый
Просмотреть файл

@ -46,6 +46,7 @@
#include <time.h>
#include "config.h"
#include "fficli.h"
#include "utils.h"
// must be placed after include "utils.h"
#ifndef RNP_USE_STD_REGEX

2
third_party/rnp/src/rnp/fficli.h поставляемый
Просмотреть файл

@ -152,6 +152,4 @@ bool rnp_casecmp(const std::string &str1, const std::string &str2);
#define EXT_PGP (".pgp")
#define EXT_GPG (".gpg")
char *rnp_strip_eol(char *s);
#endif

4
third_party/rnp/src/rnpkeys/CMakeLists.txt поставляемый
Просмотреть файл

@ -46,6 +46,10 @@ target_link_libraries(rnpkeys
JSON-C::JSON-C
)
if (WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_link_libraries(rnpkeys PRIVATE regex)
endif()
include(GNUInstallDirs)
install(TARGETS rnpkeys
RUNTIME

1
third_party/rnp/src/rnpkeys/tui.cpp поставляемый
Просмотреть файл

@ -3,6 +3,7 @@
#include "rnp/rnpcfg.h"
#include "rnpkeys.h"
#include "defaults.h"
#include "utils.h"
/* -----------------------------------------------------------------------------
* @brief Reads input from file pointer and converts it securelly to ints

5
third_party/rnp/src/tests/CMakeLists.txt поставляемый
Просмотреть файл

@ -94,6 +94,7 @@ add_executable(rnp_tests
utils-rnpcfg.cpp
issues/1030.cpp
issues/1115.cpp
issues/1171.cpp
)
target_include_directories(rnp_tests
@ -108,7 +109,9 @@ target_link_libraries(rnp_tests
JSON-C::JSON-C
gtest_main
)
if (WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_link_libraries(rnp_tests PRIVATE regex)
endif()
target_compile_definitions(rnp_tests
PRIVATE
RNP_RUN_TESTS

Двоичные данные
third_party/rnp/src/tests/data/test_messages/message.txt.enc-3key-2p поставляемый Normal file

Двоичный файл не отображается.

Двоичные данные
third_party/rnp/src/tests/data/test_messages/message.txt.enc-aead-eax поставляемый Normal file

Двоичный файл не отображается.

Двоичные данные
third_party/rnp/src/tests/data/test_messages/message.txt.enc-aead-eax-malf поставляемый Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1 @@
<EFBFBD>E ΌΚΰT#<23>\νοYΈ{Η¤ηΈΧ!tBgΓΕ¶°7%GωZ ,δφ»"R9<52>\>']<>©Θ BVΘΨ?A<>]ΩΤΐ Αqb²8j<38>dΗsι²~fΛμό‡» <0B>†y<E280A0>ξ <20><>A<EFBFBD>¦ΕΗ wή)Jθ¦ZΞ:]Ύ -aΜτΐϋcq“ <0A><> „³1ΞQ3k–w:y<>α<EFBFBD>HH<>ΰ<01>]°4°[©<>ΡU¶Kώ[rΧΔ>η*ΣU<CEA3>}‚£>ΪIϋKφΜγξ^Ό8,¶Vα ά}<7D>ΰ—I /b-/Κ€^MΝ/3<>Jΰ9…„ζA<CEB6>5¥Ψ-$–«2θ*“eΣιΛ9φrζ±αΡα½@<40>ρ-;u

Просмотреть файл

@ -0,0 +1 @@
<EFBFBD>E ΌΚΰT#<23>\νοYΈ{Η¤ηΈΧ!tBgΓΕ¶°7%GωZ ,δφ»"R9<52>\>']<>©Θ BVΘΨ?A<>]ΩΤΐ Αqb²8j<38>dΗsι²~fΛμό‡» <0B>†y<E280A0>ξ <20><>A<EFBFBD>¦ΕΗ wή)Jθ¦ZΞ:]Ύ -aΜτΐϋcq“ <0A><> „³1ΞQ3k–w:y<>α<EFBFBD>HH<>ΰ<01>]°4°[©<>ΡU¶Kώ[rΧΔ>η*ΣU<CEA3>}‚£>ΪIϋKφΜγξ^Ό8,¶Vα ά}<7D>ΰ—I /b-/Κ€^MΝ/3<>Jΰ9…„ζA<CEB6>5¥Ψ-$–«2θ*“eΣιΛ9φrζ±α<C2B1>α½@<40>ρ-;u

Двоичные данные
third_party/rnp/src/tests/data/test_messages/message.txt.enc-mdc поставляемый Normal file

Двоичный файл не отображается.

Двоичные данные
third_party/rnp/src/tests/data/test_messages/message.txt.enc-no-mdc поставляемый Normal file

Двоичный файл не отображается.

697
third_party/rnp/src/tests/ffi.cpp поставляемый
Просмотреть файл

@ -6833,6 +6833,539 @@ TEST_F(rnp_tests, test_ffi_op_verify_sig_count)
rnp_ffi_destroy(ffi);
}
TEST_F(rnp_tests, test_ffi_op_verify_get_protection_info)
{
rnp_ffi_t ffi = NULL;
rnp_input_t input = NULL;
rnp_output_t output = NULL;
// init ffi
test_ffi_init(&ffi);
assert_rnp_success(rnp_ffi_set_pass_provider(ffi, getpasscb, (void *) "password"));
/* message just signed */
assert_rnp_success(rnp_input_from_path(&input, "data/test_messages/message.txt.signed"));
assert_rnp_success(rnp_output_to_null(&output));
rnp_op_verify_t verify = NULL;
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
char *mode = NULL;
char *cipher = NULL;
bool valid = true;
assert_rnp_failure(rnp_op_verify_get_protection_info(NULL, &mode, &cipher, &valid));
assert_rnp_success(rnp_op_verify_get_protection_info(verify, &mode, NULL, NULL));
assert_int_equal(strcmp(mode, "none"), 0);
rnp_buffer_destroy(mode);
assert_rnp_success(rnp_op_verify_get_protection_info(verify, NULL, &cipher, NULL));
assert_int_equal(strcmp(cipher, "none"), 0);
rnp_buffer_destroy(cipher);
valid = true;
assert_rnp_success(rnp_op_verify_get_protection_info(verify, NULL, NULL, &valid));
assert_false(valid);
assert_rnp_failure(rnp_op_verify_get_protection_info(verify, NULL, NULL, NULL));
assert_rnp_success(rnp_op_verify_get_protection_info(verify, &mode, &cipher, &valid));
assert_int_equal(strcmp(mode, "none"), 0);
assert_int_equal(strcmp(cipher, "none"), 0);
assert_false(valid);
rnp_buffer_destroy(mode);
rnp_buffer_destroy(cipher);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
/* message without MDC */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message.txt.enc-no-mdc"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
mode = NULL;
cipher = NULL;
valid = true;
assert_rnp_success(rnp_op_verify_get_protection_info(verify, &mode, &cipher, &valid));
assert_int_equal(strcmp(mode, "cfb"), 0);
assert_int_equal(strcmp(cipher, "AES256"), 0);
assert_false(valid);
rnp_buffer_destroy(mode);
rnp_buffer_destroy(cipher);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
/* message with MDC */
assert_rnp_success(rnp_input_from_path(&input, "data/test_messages/message.txt.enc-mdc"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
mode = NULL;
cipher = NULL;
valid = false;
assert_rnp_success(rnp_op_verify_get_protection_info(verify, &mode, &cipher, &valid));
assert_int_equal(strcmp(mode, "cfb-mdc"), 0);
assert_int_equal(strcmp(cipher, "AES256"), 0);
assert_true(valid);
rnp_buffer_destroy(mode);
rnp_buffer_destroy(cipher);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
/* message with AEAD-OCB */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message.txt.enc-aead-ocb"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
mode = NULL;
cipher = NULL;
valid = false;
assert_rnp_success(rnp_op_verify_get_protection_info(verify, &mode, &cipher, &valid));
assert_int_equal(strcmp(mode, "aead-ocb"), 0);
assert_int_equal(strcmp(cipher, "CAMELLIA192"), 0);
assert_true(valid);
rnp_buffer_destroy(mode);
rnp_buffer_destroy(cipher);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
/* modified message with AEAD-OCB */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message.txt.enc-aead-ocb-malf"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_failure(rnp_op_verify_execute(verify));
mode = NULL;
cipher = NULL;
valid = false;
assert_rnp_success(rnp_op_verify_get_protection_info(verify, &mode, &cipher, &valid));
assert_int_equal(strcmp(mode, "aead-ocb"), 0);
assert_int_equal(strcmp(cipher, "CAMELLIA192"), 0);
assert_false(valid);
rnp_buffer_destroy(mode);
rnp_buffer_destroy(cipher);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
/* message with AEAD-EAX */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message.txt.enc-aead-eax"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
mode = NULL;
cipher = NULL;
valid = false;
assert_rnp_success(rnp_op_verify_get_protection_info(verify, &mode, &cipher, &valid));
assert_int_equal(strcmp(mode, "aead-eax"), 0);
assert_int_equal(strcmp(cipher, "AES256"), 0);
assert_true(valid);
rnp_buffer_destroy(mode);
rnp_buffer_destroy(cipher);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
/* modified message with AEAD-EAX */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message.txt.enc-aead-eax-malf"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_failure(rnp_op_verify_execute(verify));
mode = NULL;
cipher = NULL;
valid = false;
assert_rnp_success(rnp_op_verify_get_protection_info(verify, &mode, &cipher, &valid));
assert_int_equal(strcmp(mode, "aead-eax"), 0);
assert_int_equal(strcmp(cipher, "AES256"), 0);
assert_false(valid);
rnp_buffer_destroy(mode);
rnp_buffer_destroy(cipher);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
rnp_ffi_destroy(ffi);
}
static bool
getpasscb_for_key(rnp_ffi_t ffi,
void * app_ctx,
rnp_key_handle_t key,
const char * pgp_context,
char * buf,
size_t buf_len)
{
if (!key) {
return false;
}
char *keyid = NULL;
rnp_key_get_keyid(key, &keyid);
const char *pass = "password";
if (strcmp(keyid, (const char *) app_ctx) != 0) {
pass = "wrongpassword";
}
rnp_buffer_destroy(keyid);
strcpy(buf, pass);
return true;
}
TEST_F(rnp_tests, test_ffi_op_verify_recipients_info)
{
rnp_ffi_t ffi = NULL;
rnp_input_t input = NULL;
rnp_output_t output = NULL;
// init ffi
test_ffi_init(&ffi);
assert_rnp_success(rnp_ffi_set_pass_provider(ffi, getpasscb, (void *) "password"));
/* message just signed */
assert_rnp_success(rnp_input_from_path(&input, "data/test_messages/message.txt.signed"));
assert_rnp_success(rnp_output_to_null(&output));
rnp_op_verify_t verify = NULL;
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
/* rnp_op_verify_get_recipient_count */
assert_rnp_failure(rnp_op_verify_get_recipient_count(verify, NULL));
size_t count = 255;
assert_rnp_failure(rnp_op_verify_get_recipient_count(NULL, &count));
assert_rnp_success(rnp_op_verify_get_recipient_count(verify, &count));
assert_int_equal(count, 0);
/* rnp_op_verify_get_recipient_at */
rnp_recipient_handle_t recipient = NULL;
assert_rnp_failure(rnp_op_verify_get_recipient_at(NULL, 0, &recipient));
assert_rnp_failure(rnp_op_verify_get_recipient_at(verify, 0, NULL));
assert_rnp_failure(rnp_op_verify_get_recipient_at(verify, 0, &recipient));
assert_rnp_failure(rnp_op_verify_get_recipient_at(verify, 10, &recipient));
/* rnp_op_verify_get_used_recipient */
assert_rnp_failure(rnp_op_verify_get_used_recipient(NULL, &recipient));
assert_rnp_failure(rnp_op_verify_get_used_recipient(verify, NULL));
assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient));
assert_null(recipient);
/* rnp_op_verify_get_symenc_count */
assert_rnp_failure(rnp_op_verify_get_symenc_count(verify, NULL));
count = 255;
assert_rnp_failure(rnp_op_verify_get_symenc_count(NULL, &count));
assert_rnp_success(rnp_op_verify_get_symenc_count(verify, &count));
assert_int_equal(count, 0);
/* rnp_op_verify_get_symenc_at */
rnp_symenc_handle_t symenc = NULL;
assert_rnp_failure(rnp_op_verify_get_symenc_at(NULL, 0, &symenc));
assert_rnp_failure(rnp_op_verify_get_symenc_at(verify, 0, NULL));
assert_rnp_failure(rnp_op_verify_get_symenc_at(verify, 0, &symenc));
assert_rnp_failure(rnp_op_verify_get_symenc_at(verify, 10, &symenc));
/* rnp_op_verify_get_used_symenc */
assert_rnp_failure(rnp_op_verify_get_used_symenc(NULL, &symenc));
assert_rnp_failure(rnp_op_verify_get_used_symenc(verify, NULL));
assert_rnp_success(rnp_op_verify_get_used_symenc(verify, &symenc));
assert_null(symenc);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
/* message without MDC: single recipient */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message.txt.enc-no-mdc"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
assert_rnp_success(rnp_op_verify_get_recipient_count(verify, &count));
assert_int_equal(count, 1);
assert_rnp_failure(rnp_op_verify_get_recipient_at(verify, 1, &recipient));
assert_rnp_success(rnp_op_verify_get_recipient_at(verify, 0, &recipient));
assert_non_null(recipient);
char *alg = NULL;
assert_rnp_failure(rnp_recipient_get_alg(NULL, &alg));
assert_rnp_failure(rnp_recipient_get_alg(recipient, NULL));
assert_rnp_success(rnp_recipient_get_alg(recipient, &alg));
assert_string_equal(alg, "RSA");
rnp_buffer_destroy(alg);
char *keyid = NULL;
assert_rnp_failure(rnp_recipient_get_keyid(NULL, &keyid));
assert_rnp_failure(rnp_recipient_get_keyid(recipient, NULL));
assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid));
assert_string_equal(keyid, "8A05B89FAD5ADED1");
rnp_buffer_destroy(keyid);
recipient = NULL;
assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient));
assert_non_null(recipient);
alg = NULL;
assert_rnp_success(rnp_recipient_get_alg(recipient, &alg));
assert_string_equal(alg, "RSA");
rnp_buffer_destroy(alg);
keyid = NULL;
assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid));
assert_string_equal(keyid, "8A05B89FAD5ADED1");
rnp_buffer_destroy(keyid);
assert_rnp_success(rnp_op_verify_get_symenc_count(verify, &count));
assert_int_equal(count, 0);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
/* message with AEAD-OCB: single password */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message.txt.enc-aead-ocb"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
count = 255;
assert_rnp_success(rnp_op_verify_get_recipient_count(verify, &count));
assert_int_equal(count, 0);
assert_rnp_success(rnp_op_verify_get_symenc_count(verify, &count));
assert_int_equal(count, 1);
assert_rnp_failure(rnp_op_verify_get_symenc_at(verify, 1, &symenc));
assert_rnp_success(rnp_op_verify_get_symenc_at(verify, 0, &symenc));
assert_non_null(symenc);
char *cipher = NULL;
assert_rnp_failure(rnp_symenc_get_cipher(symenc, NULL));
assert_rnp_success(rnp_symenc_get_cipher(symenc, &cipher));
assert_string_equal(cipher, "CAMELLIA192");
rnp_buffer_destroy(cipher);
char *aead = NULL;
assert_rnp_failure(rnp_symenc_get_aead_alg(symenc, NULL));
assert_rnp_success(rnp_symenc_get_aead_alg(symenc, &aead));
assert_string_equal(aead, "OCB");
rnp_buffer_destroy(aead);
char *hash = NULL;
assert_rnp_failure(rnp_symenc_get_hash_alg(symenc, NULL));
assert_rnp_success(rnp_symenc_get_hash_alg(symenc, &hash));
assert_string_equal(hash, "SHA1");
rnp_buffer_destroy(hash);
char *s2k = NULL;
assert_rnp_failure(rnp_symenc_get_s2k_type(symenc, NULL));
assert_rnp_success(rnp_symenc_get_s2k_type(symenc, &s2k));
assert_string_equal(s2k, "Iterated and salted");
rnp_buffer_destroy(s2k);
uint32_t iterations = 0;
assert_rnp_failure(rnp_symenc_get_s2k_iterations(symenc, NULL));
assert_rnp_success(rnp_symenc_get_s2k_iterations(symenc, &iterations));
assert_int_equal(iterations, 30408704);
assert_rnp_success(rnp_op_verify_get_used_symenc(verify, &symenc));
assert_non_null(symenc);
cipher = NULL;
assert_rnp_success(rnp_symenc_get_cipher(symenc, &cipher));
assert_string_equal(cipher, "CAMELLIA192");
rnp_buffer_destroy(cipher);
aead = NULL;
assert_rnp_success(rnp_symenc_get_aead_alg(symenc, &aead));
assert_string_equal(aead, "OCB");
rnp_buffer_destroy(aead);
hash = NULL;
assert_rnp_success(rnp_symenc_get_hash_alg(symenc, &hash));
assert_string_equal(hash, "SHA1");
rnp_buffer_destroy(hash);
s2k = NULL;
assert_rnp_success(rnp_symenc_get_s2k_type(symenc, &s2k));
assert_string_equal(s2k, "Iterated and salted");
rnp_buffer_destroy(s2k);
iterations = 0;
assert_rnp_success(rnp_symenc_get_s2k_iterations(symenc, &iterations));
assert_int_equal(iterations, 30408704);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
/* modified message with AEAD-EAX: one recipient and one password, decrypt with recipient
*/
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message.txt.enc-aead-eax-malf"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_failure(rnp_op_verify_execute(verify));
count = 255;
assert_rnp_success(rnp_op_verify_get_recipient_count(verify, &count));
assert_int_equal(count, 1);
assert_rnp_success(rnp_op_verify_get_recipient_at(verify, 0, &recipient));
assert_non_null(recipient);
alg = NULL;
assert_rnp_success(rnp_recipient_get_alg(recipient, &alg));
assert_string_equal(alg, "RSA");
rnp_buffer_destroy(alg);
keyid = NULL;
assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid));
assert_string_equal(keyid, "1ED63EE56FADC34D");
rnp_buffer_destroy(keyid);
recipient = NULL;
assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient));
assert_non_null(recipient);
assert_rnp_success(rnp_recipient_get_alg(recipient, &alg));
assert_string_equal(alg, "RSA");
rnp_buffer_destroy(alg);
assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid));
assert_string_equal(keyid, "1ED63EE56FADC34D");
rnp_buffer_destroy(keyid);
assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient));
assert_non_null(recipient);
alg = NULL;
assert_rnp_success(rnp_recipient_get_alg(recipient, &alg));
assert_string_equal(alg, "RSA");
rnp_buffer_destroy(alg);
keyid = NULL;
assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid));
assert_string_equal(keyid, "1ED63EE56FADC34D");
rnp_buffer_destroy(keyid);
recipient = NULL;
assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient));
assert_non_null(recipient);
assert_rnp_success(rnp_recipient_get_alg(recipient, &alg));
assert_string_equal(alg, "RSA");
rnp_buffer_destroy(alg);
assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid));
assert_string_equal(keyid, "1ED63EE56FADC34D");
rnp_buffer_destroy(keyid);
count = 255;
assert_rnp_success(rnp_op_verify_get_symenc_count(verify, &count));
assert_int_equal(count, 1);
assert_rnp_success(rnp_op_verify_get_symenc_at(verify, 0, &symenc));
assert_non_null(symenc);
cipher = NULL;
assert_rnp_success(rnp_symenc_get_cipher(symenc, &cipher));
assert_string_equal(cipher, "AES256");
rnp_buffer_destroy(cipher);
aead = NULL;
assert_rnp_success(rnp_symenc_get_aead_alg(symenc, &aead));
assert_string_equal(aead, "EAX");
rnp_buffer_destroy(aead);
hash = NULL;
assert_rnp_success(rnp_symenc_get_hash_alg(symenc, &hash));
assert_string_equal(hash, "SHA256");
rnp_buffer_destroy(hash);
s2k = NULL;
assert_rnp_success(rnp_symenc_get_s2k_type(symenc, &s2k));
assert_string_equal(s2k, "Iterated and salted");
rnp_buffer_destroy(s2k);
iterations = 0;
assert_rnp_success(rnp_symenc_get_s2k_iterations(symenc, &iterations));
assert_int_equal(iterations, 3932160);
assert_rnp_success(rnp_op_verify_get_used_symenc(verify, &symenc));
assert_null(symenc);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
/* message with AEAD-EAX: one recipient and one password, decrypt with password */
assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_SECRET));
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message.txt.enc-aead-eax"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
count = 255;
assert_rnp_success(rnp_op_verify_get_recipient_count(verify, &count));
assert_int_equal(count, 1);
assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient));
assert_null(recipient);
count = 255;
assert_rnp_success(rnp_op_verify_get_symenc_count(verify, &count));
assert_int_equal(count, 1);
assert_rnp_success(rnp_op_verify_get_symenc_at(verify, 0, &symenc));
assert_non_null(symenc);
assert_rnp_success(rnp_op_verify_get_used_symenc(verify, &symenc));
assert_non_null(symenc);
cipher = NULL;
assert_rnp_success(rnp_symenc_get_cipher(symenc, &cipher));
assert_string_equal(cipher, "AES256");
rnp_buffer_destroy(cipher);
aead = NULL;
assert_rnp_success(rnp_symenc_get_aead_alg(symenc, &aead));
assert_string_equal(aead, "EAX");
rnp_buffer_destroy(aead);
hash = NULL;
assert_rnp_success(rnp_symenc_get_hash_alg(symenc, &hash));
assert_string_equal(hash, "SHA256");
rnp_buffer_destroy(hash);
s2k = NULL;
assert_rnp_success(rnp_symenc_get_s2k_type(symenc, &s2k));
assert_string_equal(s2k, "Iterated and salted");
rnp_buffer_destroy(s2k);
iterations = 0;
assert_rnp_success(rnp_symenc_get_s2k_iterations(symenc, &iterations));
assert_int_equal(iterations, 3932160);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
/* message encrypted to 3 recipients and 2 passwords: password1, password2 */
assert_rnp_success(rnp_ffi_set_pass_provider(ffi, getpasscb, (void *) "wrongpassword"));
assert_rnp_success(rnp_input_from_path(&input, "data/keyrings/1/secring.gpg"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_SECRET_KEYS, NULL));
rnp_input_destroy(input);
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message.txt.enc-3key-2p"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_failure(rnp_op_verify_execute(verify));
count = 255;
assert_rnp_success(rnp_op_verify_get_recipient_count(verify, &count));
assert_int_equal(count, 3);
assert_rnp_success(rnp_op_verify_get_recipient_at(verify, 0, &recipient));
assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid));
assert_string_equal(keyid, "1ED63EE56FADC34D");
rnp_buffer_destroy(keyid);
assert_rnp_success(rnp_op_verify_get_recipient_at(verify, 1, &recipient));
assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid));
assert_string_equal(keyid, "8A05B89FAD5ADED1");
rnp_buffer_destroy(keyid);
assert_rnp_success(rnp_op_verify_get_recipient_at(verify, 2, &recipient));
assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid));
assert_string_equal(keyid, "54505A936A4A970E");
rnp_buffer_destroy(keyid);
assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient));
assert_null(recipient);
count = 255;
assert_rnp_success(rnp_op_verify_get_symenc_count(verify, &count));
assert_int_equal(count, 2);
assert_rnp_success(rnp_op_verify_get_symenc_at(verify, 0, &symenc));
assert_rnp_success(rnp_symenc_get_s2k_iterations(symenc, &iterations));
assert_int_equal(iterations, 3932160);
assert_rnp_success(rnp_op_verify_get_symenc_at(verify, 1, &symenc));
assert_rnp_success(rnp_symenc_get_s2k_iterations(symenc, &iterations));
assert_int_equal(iterations, 3276800);
assert_rnp_success(rnp_op_verify_get_used_symenc(verify, &symenc));
assert_null(symenc);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
assert_rnp_success(rnp_ffi_set_pass_provider(ffi, getpasscb, (void *) "password2"));
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message.txt.enc-3key-2p"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
assert_rnp_success(rnp_op_verify_get_used_symenc(verify, &symenc));
assert_rnp_success(rnp_symenc_get_s2k_iterations(symenc, &iterations));
assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient));
assert_null(recipient);
assert_int_equal(iterations, 3276800);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
assert_rnp_success(
rnp_ffi_set_pass_provider(ffi, getpasscb_for_key, (void *) "8A05B89FAD5ADED1"));
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message.txt.enc-3key-2p"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
assert_rnp_success(rnp_op_verify_get_used_symenc(verify, &symenc));
assert_null(symenc);
assert_rnp_success(rnp_op_verify_get_used_recipient(verify, &recipient));
assert_rnp_success(rnp_recipient_get_keyid(recipient, &keyid));
assert_string_equal(keyid, "8A05B89FAD5ADED1");
rnp_buffer_destroy(keyid);
rnp_op_verify_destroy(verify);
rnp_input_destroy(input);
rnp_output_destroy(output);
rnp_ffi_destroy(ffi);
}
static bool
check_import_sigs(rnp_ffi_t ffi, json_object **jso, json_object **sigarr, const char *sigpath)
{
@ -7860,3 +8393,167 @@ TEST_F(rnp_tests, test_ffi_key_import_edge_cases)
rnp_ffi_destroy(ffi);
}
TEST_F(rnp_tests, test_ffi_key_remove)
{
rnp_ffi_t ffi = NULL;
test_ffi_init(&ffi);
rnp_key_handle_t key0 = NULL;
rnp_key_handle_t key0_sub0 = NULL;
rnp_key_handle_t key0_sub1 = NULL;
rnp_key_handle_t key0_sub2 = NULL;
assert_rnp_success(rnp_locate_key(ffi, "keyid", "7bc6709b15c23a4a", &key0));
assert_rnp_success(rnp_locate_key(ffi, "keyid", "1ed63ee56fadc34d", &key0_sub0));
assert_rnp_success(rnp_locate_key(ffi, "keyid", "1d7e8a5393c997a8", &key0_sub1));
assert_rnp_success(rnp_locate_key(ffi, "keyid", "8a05b89fad5aded1", &key0_sub2));
/* edge cases */
assert_rnp_failure(rnp_key_remove(NULL, RNP_KEY_REMOVE_PUBLIC));
assert_rnp_failure(rnp_key_remove(key0, 0));
/* make sure we correctly remove public and secret keys */
bool pub = false;
assert_rnp_success(rnp_key_have_public(key0_sub2, &pub));
assert_true(pub);
bool sec = false;
assert_rnp_success(rnp_key_have_secret(key0_sub2, &sec));
assert_true(sec);
assert_rnp_success(rnp_key_remove(key0_sub2, RNP_KEY_REMOVE_PUBLIC));
pub = true;
assert_rnp_success(rnp_key_have_public(key0_sub2, &pub));
assert_false(pub);
sec = false;
assert_rnp_success(rnp_key_have_secret(key0_sub2, &sec));
assert_true(sec);
assert_rnp_failure(rnp_key_remove(key0_sub2, RNP_KEY_REMOVE_PUBLIC));
rnp_key_handle_destroy(key0_sub2);
/* locate it back */
assert_rnp_success(rnp_locate_key(ffi, "keyid", "8a05b89fad5aded1", &key0_sub2));
assert_non_null(key0_sub2);
pub = true;
assert_rnp_success(rnp_key_have_public(key0_sub2, &pub));
assert_false(pub);
sec = false;
assert_rnp_success(rnp_key_have_secret(key0_sub2, &sec));
assert_true(sec);
pub = false;
assert_rnp_success(rnp_key_have_public(key0_sub0, &pub));
assert_true(pub);
sec = false;
assert_rnp_success(rnp_key_have_secret(key0_sub0, &sec));
assert_true(sec);
assert_rnp_success(rnp_key_remove(key0_sub0, RNP_KEY_REMOVE_SECRET));
pub = false;
assert_rnp_success(rnp_key_have_public(key0_sub0, &pub));
assert_true(pub);
sec = true;
assert_rnp_success(rnp_key_have_secret(key0_sub0, &sec));
assert_false(sec);
assert_rnp_failure(rnp_key_remove(key0_sub0, RNP_KEY_REMOVE_SECRET));
rnp_key_handle_destroy(key0_sub0);
assert_rnp_success(rnp_locate_key(ffi, "keyid", "1ed63ee56fadc34d", &key0_sub0));
assert_non_null(key0_sub0);
size_t count = 0;
assert_rnp_success(rnp_get_public_key_count(ffi, &count));
assert_int_equal(count, 6);
count = 0;
assert_rnp_success(rnp_get_secret_key_count(ffi, &count));
assert_int_equal(count, 6);
/* while there are 2 public and 1 secret subkey, this calculates only public */
assert_rnp_success(rnp_key_get_subkey_count(key0, &count));
assert_int_equal(count, 2);
assert_rnp_success(rnp_key_remove(key0_sub0, RNP_KEY_REMOVE_PUBLIC));
assert_rnp_success(rnp_key_get_subkey_count(key0, &count));
assert_int_equal(count, 1);
count = 0;
assert_rnp_success(rnp_get_public_key_count(ffi, &count));
assert_int_equal(count, 5);
assert_rnp_success(rnp_get_secret_key_count(ffi, &count));
assert_int_equal(count, 6);
assert_rnp_success(rnp_key_remove(key0_sub2, RNP_KEY_REMOVE_SECRET));
assert_rnp_success(rnp_key_get_subkey_count(key0, &count));
assert_int_equal(count, 1);
assert_rnp_success(rnp_get_secret_key_count(ffi, &count));
assert_int_equal(count, 5);
assert_rnp_success(rnp_key_remove(key0, RNP_KEY_REMOVE_PUBLIC | RNP_KEY_REMOVE_SECRET));
assert_rnp_success(rnp_get_public_key_count(ffi, &count));
assert_int_equal(count, 4);
assert_rnp_success(rnp_get_secret_key_count(ffi, &count));
assert_int_equal(count, 4);
rnp_key_handle_destroy(key0_sub1);
/* key0_sub1 should be left in keyring */
assert_rnp_success(rnp_locate_key(ffi, "keyid", "1d7e8a5393c997a8", &key0_sub1));
pub = false;
assert_rnp_success(rnp_key_have_public(key0_sub1, &pub));
assert_true(pub);
sec = false;
assert_rnp_success(rnp_key_have_secret(key0_sub1, &sec));
assert_true(sec);
rnp_key_handle_destroy(key0);
rnp_key_handle_destroy(key0_sub0);
rnp_key_handle_destroy(key0_sub1);
rnp_key_handle_destroy(key0_sub2);
/* let's import keys back */
rnp_input_t input = NULL;
assert_rnp_success(rnp_input_from_path(&input, "data/keyrings/1/pubring.gpg"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
rnp_input_destroy(input);
assert_rnp_success(rnp_input_from_path(&input, "data/keyrings/1/secring.gpg"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_SECRET_KEYS, NULL));
rnp_input_destroy(input);
assert_rnp_success(rnp_get_public_key_count(ffi, &count));
assert_int_equal(count, 7);
assert_rnp_success(rnp_get_secret_key_count(ffi, &count));
assert_int_equal(count, 7);
/* now try to remove the whole key */
assert_rnp_success(rnp_locate_key(ffi, "keyid", "7bc6709b15c23a4a", &key0));
assert_rnp_success(rnp_locate_key(ffi, "keyid", "1ed63ee56fadc34d", &key0_sub0));
assert_rnp_failure(
rnp_key_remove(key0_sub0, RNP_KEY_REMOVE_SECRET | RNP_KEY_REMOVE_SUBKEYS));
assert_rnp_success(rnp_key_remove(key0_sub0, RNP_KEY_REMOVE_SECRET));
assert_rnp_success(rnp_key_remove(key0_sub0, RNP_KEY_REMOVE_PUBLIC));
assert_rnp_success(rnp_get_public_key_count(ffi, &count));
assert_int_equal(count, 6);
assert_rnp_success(rnp_get_secret_key_count(ffi, &count));
assert_int_equal(count, 6);
assert_rnp_success(rnp_key_remove(key0, RNP_KEY_REMOVE_SECRET | RNP_KEY_REMOVE_SUBKEYS));
assert_rnp_success(rnp_get_public_key_count(ffi, &count));
assert_int_equal(count, 6);
assert_rnp_success(rnp_get_secret_key_count(ffi, &count));
assert_int_equal(count, 3);
assert_rnp_success(rnp_key_remove(key0, RNP_KEY_REMOVE_PUBLIC | RNP_KEY_REMOVE_SUBKEYS));
assert_rnp_success(rnp_get_public_key_count(ffi, &count));
assert_int_equal(count, 3);
assert_rnp_success(rnp_get_secret_key_count(ffi, &count));
assert_int_equal(count, 3);
rnp_key_handle_destroy(key0);
rnp_key_handle_destroy(key0_sub0);
/* delete the second key all at once */
assert_rnp_success(rnp_locate_key(ffi, "keyid", "2fcadf05ffa501bb", &key0));
assert_rnp_success(rnp_key_remove(
key0, RNP_KEY_REMOVE_PUBLIC | RNP_KEY_REMOVE_SECRET | RNP_KEY_REMOVE_SUBKEYS));
assert_rnp_success(rnp_get_public_key_count(ffi, &count));
assert_int_equal(count, 0);
assert_rnp_success(rnp_get_secret_key_count(ffi, &count));
assert_int_equal(count, 0);
rnp_key_handle_destroy(key0);
rnp_ffi_destroy(ffi);
}

74
third_party/rnp/src/tests/issues/1171.cpp поставляемый Normal file
Просмотреть файл

@ -0,0 +1,74 @@
/*
* Copyright (c) 2020 [Ribose Inc](https://www.ribose.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "../rnp_tests.h"
#include "../support.h"
#include <librepgp/stream-ctx.h>
#include "pgp-key.h"
#include "ffi-priv-types.h"
TEST_F(rnp_tests, test_issue_1171_key_import_and_remove)
{
rnp_ffi_t ffi = NULL;
assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG"));
rnp_input_t input = NULL;
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/alice-sub-pub.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
rnp_input_destroy(input);
rnp_key_handle_t key = NULL;
assert_rnp_success(
rnp_locate_key(ffi, "grip", "3E3D52A346F0AD47754611B078117C240ED237E9", &key));
assert_non_null(key);
assert_rnp_success(rnp_key_remove(key, RNP_KEY_REMOVE_PUBLIC));
assert_rnp_success(rnp_key_handle_destroy(key));
assert_rnp_success(
rnp_locate_key(ffi, "grip", "3E3D52A346F0AD47754611B078117C240ED237E9", &key));
assert_null(key);
assert_rnp_success(
rnp_locate_key(ffi, "grip", "128E494F41F107E119AA1EEF7850C375A804341C", &key));
assert_non_null(key);
uint32_t bits = 0;
assert_rnp_success(rnp_key_get_bits(key, &bits));
assert_int_equal(bits, 256);
/* directly use rnp_key_store_get_key_by_grip() which caused crash */
pgp_key_t *subkey =
rnp_key_store_get_key_by_grip(ffi->pubring, pgp_key_get_grip(key->pub));
assert_int_equal(pgp_key_get_bits(subkey), 256);
assert_rnp_success(rnp_key_handle_destroy(key));
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/alice-sub-pub.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
rnp_input_destroy(input);
rnp_ffi_destroy(ffi);
}

10
third_party/rnp/src/tests/rnp_tests.h поставляемый
Просмотреть файл

@ -277,6 +277,10 @@ void test_ffi_detached_verify_input(void **state);
void test_ffi_op_verify_sig_count(void **state);
void test_ffi_op_verify_get_protection_info(void **state);
void test_ffi_op_verify_recipients_info(void **state);
void test_ffi_import_signatures(void **state);
void test_ffi_export_revocation(void **state);
@ -295,6 +299,8 @@ void test_ffi_decrypt_wrong_mpi_bits(void **state);
void test_ffi_key_import_edge_cases(void **state);
void test_ffi_key_remove(void **state);
void test_dsa_roundtrip(void **state);
void test_dsa_verify_negative(void **state);
@ -369,6 +375,10 @@ void test_kbx_nsigs(void **state);
void test_issue_1115(void **state);
void issue_1030_rnpkeys_secret_keys_unprotected(void **state);
void test_issue_1171_key_import_and_remove(void **state);
void test_log_switch(void **state);
#define assert_true(a) EXPECT_TRUE((a))