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:
Родитель
bdf29458a7
Коммит
66eff79245
|
@ -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 *);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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(¶m->symencs);
|
||||
list_destroy(¶m->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(¶m->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(¶m->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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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-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
поставляемый
Normal file
Двоичный файл не отображается.
Двоичные данные
third_party/rnp/src/tests/data/test_messages/message.txt.enc-aead-eax-malf
поставляемый
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ΗsuΓι²~fΛμό‡»<0B>†y<E280A0>ξ <20><>A<EFBFBD>¦ΕΗwή)Jθ¦ZΞ›:]Ύ -aΜτΐϋcq“
<0A><>sέ „³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
|
1
third_party/rnp/src/tests/data/test_messages/message.txt.enc-aead-ocb-malf
поставляемый
Normal file
1
third_party/rnp/src/tests/data/test_messages/message.txt.enc-aead-ocb-malf
поставляемый
Normal file
|
@ -0,0 +1 @@
|
|||
<EFBFBD>EΌΚΰT#<23>\νοYΈ{Η¤ηΈΧ!tBgΓΕ¶°’7%GωZ
,δφ»"R9<52>\>']’<>©Θ BVΘΨ?A<>‘]ΩΤΐΑ‚qb²8j<38>dΗsuΓι²~fΛμό‡»<0B>†y<E280A0>ξ <20><>A<EFBFBD>¦ΕΗwή)Jθ¦ZΞ›:]Ύ -aΜτΐϋcq“
<0A><>sέ „³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-mdc
поставляемый
Normal file
Двоичный файл не отображается.
Двоичные данные
third_party/rnp/src/tests/data/test_messages/message.txt.enc-no-mdc
поставляемый
Normal file
Двоичные данные
third_party/rnp/src/tests/data/test_messages/message.txt.enc-no-mdc
поставляемый
Normal file
Двоичный файл не отображается.
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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))
|
||||
|
|
Загрузка…
Ссылка в новой задаче