Bug 1634158 - Update RNP source from git as of 2020-05-06. r=kaie

Using update_rnp.sh.
Revision: eabaa5d07ae453c44dfa272f25ad7b5e41c8e5fb

--HG--
extra : rebase_source : e0aa4b42ef566c98f91629a56707ca87fd25947f
extra : histedit_source : a8e4c98f8f2a97fde14bd4bc564304e31592dbcf
This commit is contained in:
Rob Lemley 2020-05-07 13:23:01 -04:00
Родитель 1d68def8c0
Коммит a089e7e968
60 изменённых файлов: 2806 добавлений и 1137 удалений

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

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

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

@ -93,7 +93,7 @@ pacman -Syu --noconfirm --needed
# Then most likely you'll need to close msys console and run it agian:
pacman -Syu --noconfirm --needed
# Install packages
pacman --noconfirm -S --needed tar zlib-devel libbz2-devel git automake autoconf libtool automake-wrapper gnupg2 make pkgconfig mingw64/mingw-w64-x86_64-cmake mingw64/mingw-w64-x86_64-gcc mingw64/mingw-w64-x86_64-json-c mingw64/mingw-w64-x86_64-libbotan mingw64/mingw-w64-x86_64-python2
pacman --noconfirm -S --needed tar zlib-devel libbz2-devel git automake autoconf libtool automake-wrapper gnupg2 make pkgconfig mingw64/mingw-w64-x86_64-cmake mingw64/mingw-w64-x86_64-gcc mingw64/mingw-w64-x86_64-json-c mingw64/mingw-w64-x86_64-libbotan mingw64/mingw-w64-x86_64-python3
----
Then clone the repository, say to rnp folder, and:

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

@ -155,7 +155,14 @@ size_t rnp_key_store_get_key_count(const rnp_key_store_t *);
pgp_key_t *rnp_key_store_get_key(const rnp_key_store_t *, size_t);
list rnp_key_store_get_keys(const rnp_key_store_t *);
pgp_key_t *rnp_key_store_add_key(rnp_key_store_t *, pgp_key_t *);
/**
* @brief Add key to the keystore, copying it.
*
* @param keyring allocated keyring, cannot be NULL.
* @param key key to be added, cannot be NULL.
* @return pointer to the added key or NULL if failed.
*/
pgp_key_t *rnp_key_store_add_key(rnp_key_store_t *keyring, pgp_key_t *key);
pgp_key_t *rnp_key_store_import_key(rnp_key_store_t *,
pgp_key_t *,
@ -171,6 +178,10 @@ pgp_key_t *rnp_key_store_import_key(rnp_key_store_t *,
*/
pgp_key_t *rnp_key_store_get_signer_key(rnp_key_store_t *store, const pgp_signature_t *sig);
pgp_sig_import_status_t rnp_key_store_import_key_signature(rnp_key_store_t * keyring,
pgp_key_t * key,
const pgp_signature_t *sig);
/**
* @brief Import revocation or direct-key signature to the keyring.
*

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

@ -340,6 +340,7 @@ typedef enum {
*/
typedef enum {
PGP_SIG_SUBPKT_UNKNOWN = 0,
PGP_SIG_SUBPKT_CREATION_TIME = 2, /* signature creation time */
PGP_SIG_SUBPKT_EXPIRATION_TIME = 3, /* signature expiration time */
PGP_SIG_SUBPKT_EXPORT_CERT = 4, /* exportable certification */

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

@ -856,6 +856,27 @@ rnp_result_t rnp_key_export_revocation(rnp_key_handle_t key,
const char * code,
const char * reason);
/**
* @brief revoke a key or subkey by generating and adding revocation signature.
* @param key key or subkey to be revoked. For primary key must have secret key, otherwise
* keyrings will be searched for the authorized to issue revocation signatures
* secret key. For subkey keyrings must have primary secret key.
* If secret key is locked then password will be asked via password provider.
* @param flags currently must be 0.
* @param hash hash algorithm used to calculate signature. Pass NULL for default algorithm
* selection.
* @param code reason for revocation code. Possible values: 'no', 'superseded', 'compromised',
* 'retired'. May be NULL - then 'no' value will be used.
* @param reason textual representation of the reason for revocation. May be NULL or empty
* string.
* @return RNP_SUCCESS on success, or any other value on error
*/
rnp_result_t rnp_key_revoke(rnp_key_handle_t key,
uint32_t flags,
const char * hash,
const char * code,
const char * reason);
/** remove a key from keyring(s)
* 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.
@ -1206,6 +1227,18 @@ rnp_result_t rnp_key_get_creation(rnp_key_handle_t key, uint32_t *result);
*/
rnp_result_t rnp_key_get_expiration(rnp_key_handle_t key, uint32_t *result);
/**
* @brief Set the key's expiration time in seconds.
* Note: this will require re-signing, which requires availability of the secret key (or
* secret primary key for the subkey). If the secret key is locked then may ask for
* key's password via FFI callback.
*
* @param key key's handle.
* @param expiry expiration time in seconds (or 0 if key doesn't expire).
* @return RNP_SUCCESS or error code on failure.
*/
rnp_result_t rnp_key_set_expiration(rnp_key_handle_t key, uint32_t expiry);
/**
* @brief Check whether key is revoked.
*
@ -1347,8 +1380,6 @@ rnp_result_t rnp_key_is_sub(rnp_key_handle_t key, bool *result);
rnp_result_t rnp_key_have_secret(rnp_key_handle_t key, bool *result);
rnp_result_t rnp_key_have_public(rnp_key_handle_t key, bool *result);
/* TODO: function to add a userid to a key */
/** Get the information about key packets in JSON string.
* Note: this will not work for G10 keys.
*
@ -1662,8 +1693,6 @@ rnp_result_t rnp_op_verify_signature_get_times(rnp_op_verify_signature_t sig,
uint32_t * create,
uint32_t * expires);
/* TODO define functions for encrypt+sign */
/**
* @brief Free buffer allocated by a function in this header.
*

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

@ -24,7 +24,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#define PACKAGE_STRING "rnp 0.13.1+git20200402.5f41ee12.MZLA"
#define PACKAGE_STRING "rnp 0.13.1+git20200506.eabaa5d0.MZLA"
#define PACKAGE_BUGREPORT "https://bugzilla.mozilla.org/enter_bug.cgi?product=Thunderbird"
#undef HAVE_BZLIB_H

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

@ -132,10 +132,7 @@ load_generated_g10_key(pgp_key_t * dst,
if (rnp_key_store_get_key_count(key_store) != 1) {
goto end;
}
memcpy(dst, rnp_key_store_get_key(key_store, 0), sizeof(*dst));
// we don't want the key store to free the internal key data
rnp_key_store_remove_key(key_store, (pgp_key_t *) rnp_key_store_get_key(key_store, 0));
ok = true;
ok = !pgp_key_copy(dst, rnp_key_store_get_key(key_store, 0), false);
end:
rnp_key_store_free(key_store);
src_close(&memsrc);
@ -331,6 +328,18 @@ keygen_primary_merge_defaults(rnp_keygen_primary_desc_t *desc)
}
}
static void
pgp_key_mark_valid(pgp_key_t *key)
{
key->valid = true;
key->validated = true;
for (size_t i = 0; i < pgp_key_get_subsig_count(key); i++) {
pgp_subsig_t *sub = pgp_key_get_subsig(key, i);
sub->validated = true;
sub->valid = true;
}
}
bool
pgp_generate_primary_key(rnp_keygen_primary_desc_t *desc,
bool merge_defaults,
@ -408,22 +417,16 @@ pgp_generate_primary_key(rnp_keygen_primary_desc_t *desc,
}
/* mark it as valid */
primary_pub->valid = true;
primary_pub->validated = true;
primary_sec->valid = true;
primary_sec->validated = true;
ok = true;
pgp_key_mark_valid(primary_pub);
pgp_key_mark_valid(primary_sec);
/* refresh key's data */
ok = pgp_key_refresh_data(primary_pub) && pgp_key_refresh_data(primary_sec);
end:
// free any user preferences
pgp_free_user_prefs(&desc->cert.prefs);
// we don't need this as we have loaded the encrypted key into primary_sec
transferable_key_destroy(&tkeysec);
transferable_key_destroy(&tkeypub);
if (!ok) {
pgp_key_free_data(primary_pub);
pgp_key_free_data(primary_sec);
}
return ok;
}
@ -545,18 +548,13 @@ pgp_generate_subkey(rnp_keygen_subkey_desc_t * desc,
break;
}
subkey_pub->valid = true;
subkey_pub->validated = true;
subkey_sec->valid = true;
subkey_sec->validated = true;
ok = true;
pgp_key_mark_valid(subkey_pub);
pgp_key_mark_valid(subkey_sec);
ok = pgp_subkey_refresh_data(subkey_pub, primary_pub) &&
pgp_subkey_refresh_data(subkey_sec, primary_sec);
end:
transferable_subkey_destroy(&tskeysec);
transferable_subkey_destroy(&tskeypub);
if (!ok) {
pgp_key_free_data(subkey_pub);
pgp_key_free_data(subkey_sec);
}
if (decrypted_primary_seckey) {
free_key_pkt(decrypted_primary_seckey);
free(decrypted_primary_seckey);

1204
third_party/rnp/src/lib/pgp-key.cpp поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -54,6 +54,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <vector>
#include "pass-provider.h"
#include <rekey/rnp_key_store.h>
#include "crypto/symmetric.h"
@ -61,12 +62,13 @@
/* describes a user's key */
struct pgp_key_t {
list uids; /* list of user ids as (char*) */
list packets; /* list of raw packets as pgp_rawpacket_t */
list subsigs; /* list of signatures as pgp_subsig_t */
list revokes; /* list of signature revocations pgp_revoke_t */
std::vector<pgp_userid_t> uids; /* array of user ids */
std::vector<pgp_rawpacket_t> packets; /* array of key packets */
std::vector<pgp_subsig_t> subsigs; /* array of key signatures */
std::vector<pgp_revoke_t> revokes; /* array of revocations */
list subkey_grips; /* list of subkey grips (for primary keys) as uint8_t[20] */
uint8_t * primary_grip; /* grip of primary key (for subkeys) */
uint8_t primary_grip[PGP_KEY_GRIP_SIZE]; /* grip of primary key (for subkeys) */
bool primary_grip_set;
time_t expiration; /* key expiration time, if available */
pgp_key_pkt_t pkt; /* pubkey/seckey data packet */
uint8_t key_flags; /* key flags */
@ -80,9 +82,15 @@ struct pgp_key_t {
pgp_key_store_format_t format; /* the format of the key in packets[0] */
bool valid; /* this key is valid and usable */
bool validated; /* this key was validated */
};
struct pgp_key_t *pgp_key_new(void);
~pgp_key_t();
pgp_key_t() = default;
pgp_key_t &operator=(pgp_key_t &&);
/* make sure we use only empty constructor/move operator */
pgp_key_t(const pgp_key_t &src) = delete;
pgp_key_t(pgp_key_t &&src) = delete;
pgp_key_t &operator=(const pgp_key_t &) = delete;
};
/**
* @brief Create pgp_key_t object from the OpenPGP key packet.
@ -93,20 +101,6 @@ struct pgp_key_t *pgp_key_new(void);
*/
bool pgp_key_from_pkt(pgp_key_t *key, const pgp_key_pkt_t *pkt);
/** free the internal data of a key *and* the key structure itself
*
* @param key the key
**/
void pgp_key_free(pgp_key_t *);
/** free the internal data of a key
*
* This does *not* free the key structure itself.
*
* @param key the key
**/
void pgp_key_free_data(pgp_key_t *);
/**
* @brief Copy key, optionally copying only the public key part.
*
@ -236,9 +230,9 @@ const uint8_t *pgp_key_get_primary_grip(const pgp_key_t *key);
*
* @param key subkey
* @param grip buffer with grip, should not be NULL
* @return true on success or false otherwise (key is not subkey, or allocation failed)
* @return void
*/
bool pgp_key_set_primary_grip(pgp_key_t *key, const uint8_t *grip);
void pgp_key_set_primary_grip(pgp_key_t *key, const uint8_t *grip);
/**
* @brief Link key with subkey via primary_grip and subkey_grips list
@ -251,9 +245,11 @@ bool pgp_key_link_subkey_grip(pgp_key_t *key, pgp_key_t *subkey);
size_t pgp_key_get_userid_count(const pgp_key_t *);
pgp_userid_t *pgp_key_get_userid(const pgp_key_t *, size_t);
const pgp_userid_t *pgp_key_get_userid(const pgp_key_t *, size_t);
pgp_revoke_t *pgp_key_get_userid_revoke(const pgp_key_t *, size_t userid);
pgp_userid_t *pgp_key_get_userid(pgp_key_t *, size_t);
const pgp_revoke_t *pgp_key_get_userid_revoke(const pgp_key_t *, size_t userid);
bool pgp_key_has_userid(const pgp_key_t *, const char *);
@ -263,7 +259,9 @@ pgp_revoke_t *pgp_key_add_revoke(pgp_key_t *);
size_t pgp_key_get_revoke_count(const pgp_key_t *);
pgp_revoke_t *pgp_key_get_revoke(const pgp_key_t *, size_t);
const pgp_revoke_t *pgp_key_get_revoke(const pgp_key_t *, size_t);
pgp_revoke_t *pgp_key_get_revoke(pgp_key_t *key, size_t idx);
void revoke_free(pgp_revoke_t *revoke);
@ -271,7 +269,40 @@ pgp_subsig_t *pgp_key_add_subsig(pgp_key_t *);
size_t pgp_key_get_subsig_count(const pgp_key_t *);
pgp_subsig_t *pgp_key_get_subsig(const pgp_key_t *, size_t);
const pgp_subsig_t *pgp_key_get_subsig(const pgp_key_t *, size_t);
pgp_subsig_t * pgp_key_get_subsig(pgp_key_t *, size_t);
bool pgp_subsig_from_signature(pgp_subsig_t *subsig, const pgp_signature_t *sig);
bool pgp_key_has_signature(const pgp_key_t *key, const pgp_signature_t *sig);
pgp_subsig_t *pgp_key_replace_signature(pgp_key_t * key,
pgp_signature_t *oldsig,
pgp_signature_t *newsig);
/**
* @brief Get the latest valid self-signature with information about the primary key,
* containing the specified subpacket. It could be userid certification or direct-key
* signature.
*
* @param key key which should be searched for signature.
* @param subpkt subpacket type. Pass 0 to return just latest signature.
* @return pointer to signature object or NULL if failed/not found.
*/
pgp_subsig_t *pgp_key_latest_selfsig(pgp_key_t *key, pgp_sig_subpacket_type_t subpkt);
/**
* @brief Get the latest valid subkey binding.
*
* @param subkey subkey which should be searched for signature.
* @param validated set to true whether binding signature must be validated
* @return pointer to signature object or NULL if failed/not found.
*/
pgp_subsig_t *pgp_key_latest_binding(pgp_key_t *subkey, bool validated);
bool pgp_key_refresh_data(pgp_key_t *key);
bool pgp_subkey_refresh_data(pgp_key_t *sub, pgp_key_t *key);
void pgp_subsig_free(pgp_subsig_t *subsig);
@ -285,7 +316,8 @@ pgp_rawpacket_t *pgp_key_add_uid_rawpacket(pgp_key_t *key, const pgp_userid_pkt_
size_t pgp_key_get_rawpacket_count(const pgp_key_t *);
pgp_rawpacket_t *pgp_key_get_rawpacket(const pgp_key_t *, size_t);
pgp_rawpacket_t * pgp_key_get_rawpacket(pgp_key_t *, size_t);
const pgp_rawpacket_t *pgp_key_get_rawpacket(const pgp_key_t *, size_t);
/**
* @brief Get the number of pgp key's subkeys.
@ -412,6 +444,13 @@ bool pgp_key_add_userid_certified(pgp_key_t * key,
pgp_hash_alg_t hash_alg,
rnp_selfsig_cert_info_t *cert);
bool pgp_key_set_expiration(pgp_key_t *key, pgp_key_t *signer, uint32_t expiry);
bool pgp_subkey_set_expiration(pgp_key_t *sub,
pgp_key_t *primsec,
pgp_key_t *secsub,
uint32_t expiry);
bool pgp_key_write_packets(const pgp_key_t *key, pgp_dest_t *dst);
/**
@ -458,6 +497,10 @@ pgp_key_t *find_suitable_key(pgp_op_t op,
*/
pgp_hash_alg_t pgp_hash_adjust_alg_to_key(pgp_hash_alg_t hash, const pgp_key_pkt_t *pubkey);
rnp_result_t pgp_key_validate(pgp_key_t *key, rnp_key_store_t *keyring);
void pgp_key_validate_subkey(pgp_key_t *subkey, pgp_key_t *key);
void pgp_key_validate(pgp_key_t *key, rnp_key_store_t *keyring);
void pgp_key_revalidate_updated(pgp_key_t *key, rnp_key_store_t *keyring);
#endif // RNP_PACKET_KEY_H

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

@ -1085,15 +1085,8 @@ do_load_keys(rnp_ffi_t ffi,
goto done;
}
if ((tmpret = pgp_key_copy(&keycp, key, false))) {
FFI_LOG(ffi, "Failed to copy secret key");
ret = tmpret;
goto done;
}
if (!rnp_key_store_add_key(ffi->secring, &keycp)) {
if (!rnp_key_store_add_key(ffi->secring, key)) {
FFI_LOG(ffi, "Failed to add secret key");
pgp_key_free_data(&keycp);
ret = RNP_ERROR_GENERIC;
goto done;
}
@ -1118,14 +1111,12 @@ do_load_keys(rnp_ffi_t ffi,
if (key_needs_conversion(key, ffi->pubring)) {
FFI_LOG(ffi, "This key format conversion is not yet supported");
pgp_key_free_data(&keycp);
ret = RNP_ERROR_NOT_IMPLEMENTED;
goto done;
}
if (!rnp_key_store_add_key(ffi->pubring, &keycp)) {
FFI_LOG(ffi, "Failed to add public key");
pgp_key_free_data(&keycp);
ret = RNP_ERROR_GENERIC;
goto done;
}
@ -1467,14 +1458,8 @@ done:
static bool
copy_store_keys(rnp_ffi_t ffi, rnp_key_store_t *dest, rnp_key_store_t *src)
{
pgp_key_t keycp = {};
for (list_item *key = list_front(rnp_key_store_get_keys(src)); key; key = list_next(key)) {
if (pgp_key_copy(&keycp, (pgp_key_t *) key, false)) {
FFI_LOG(ffi, "failed to create key copy");
return false;
}
if (!rnp_key_store_add_key(dest, &keycp)) {
pgp_key_free_data(&keycp);
if (!rnp_key_store_add_key(dest, (pgp_key_t *) key)) {
FFI_LOG(ffi, "failed to add key to the store");
return false;
}
@ -3282,6 +3267,51 @@ rnp_key_export_revocation(rnp_key_handle_t key,
return ret;
}
rnp_result_t
rnp_key_revoke(
rnp_key_handle_t key, uint32_t flags, const char *hash, const char *code, const char *reason)
{
if (!key || !key->ffi) {
return RNP_ERROR_NULL_POINTER;
}
if (flags) {
return RNP_ERROR_BAD_PARAMETERS;
}
pgp_key_t *exkey = get_key_prefer_public(key);
if (!exkey) {
return RNP_ERROR_BAD_PARAMETERS;
}
pgp_key_t *revoker = rnp_key_get_revoker(key);
if (!revoker) {
FFI_LOG(key->ffi, "Revoker secret key not found");
return RNP_ERROR_BAD_PARAMETERS;
}
pgp_signature_t *sig = NULL;
rnp_result_t ret =
rnp_key_get_revocation(key->ffi, exkey, revoker, hash, code, reason, &sig);
if (ret) {
return ret;
}
pgp_sig_import_status_t pub_status = PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY;
pgp_sig_import_status_t sec_status = PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY;
if (key->pub) {
pub_status = rnp_key_store_import_key_signature(key->ffi->pubring, key->pub, sig);
}
if (key->sec) {
sec_status = rnp_key_store_import_key_signature(key->ffi->secring, key->sec, sig);
}
free_signature(sig);
free(sig);
if ((pub_status == PGP_SIG_IMPORT_STATUS_UNKNOWN) ||
(sec_status == PGP_SIG_IMPORT_STATUS_UNKNOWN)) {
return RNP_ERROR_GENERIC;
}
return RNP_SUCCESS;
}
rnp_result_t
rnp_key_remove(rnp_key_handle_t key, uint32_t flags)
{
@ -3295,7 +3325,6 @@ rnp_key_remove(rnp_key_handle_t key, uint32_t flags)
if (!key->ffi->pubring || !key->pub) {
return RNP_ERROR_BAD_PARAMETERS;
}
pgp_key_free_data(key->pub);
if (!rnp_key_store_remove_key(key->ffi->pubring, key->pub)) {
return RNP_ERROR_KEY_NOT_FOUND;
}
@ -3305,7 +3334,6 @@ rnp_key_remove(rnp_key_handle_t key, uint32_t flags)
if (!key->ffi->secring || !key->sec) {
return RNP_ERROR_BAD_PARAMETERS;
}
pgp_key_free_data(key->sec);
if (!rnp_key_store_remove_key(key->ffi->secring, key->sec)) {
return RNP_ERROR_KEY_NOT_FOUND;
}
@ -3738,10 +3766,10 @@ rnp_generate_key_json(rnp_ffi_t ffi, const char *json, char **results)
rnp_action_keygen_t keygen_desc = {};
char * identifier_type = NULL;
char * identifier = NULL;
pgp_key_t primary_pub = {0};
pgp_key_t primary_sec = {0};
pgp_key_t sub_pub = {0};
pgp_key_t sub_sec = {0};
pgp_key_t primary_pub = {};
pgp_key_t primary_sec = {};
pgp_key_t sub_pub = {};
pgp_key_t sub_sec = {};
json_object * jsoprimary = NULL;
json_object * jsosub = NULL;
json_tokener_error error;
@ -3812,12 +3840,10 @@ rnp_generate_key_json(rnp_ffi_t ffi, const char *json, char **results)
ret = RNP_ERROR_OUT_OF_MEMORY;
goto done;
}
primary_pub = (pgp_key_t){0};
if (!rnp_key_store_add_key(ffi->pubring, &sub_pub)) {
ret = RNP_ERROR_OUT_OF_MEMORY;
goto done;
}
sub_pub = (pgp_key_t){0};
}
/* add key/subkey protection */
if (keygen_desc.primary.protection.symm_alg &&
@ -3842,12 +3868,10 @@ rnp_generate_key_json(rnp_ffi_t ffi, const char *json, char **results)
ret = RNP_ERROR_OUT_OF_MEMORY;
goto done;
}
primary_sec = (pgp_key_t){0};
if (!rnp_key_store_add_key(ffi->secring, &sub_sec)) {
ret = RNP_ERROR_OUT_OF_MEMORY;
goto done;
}
sub_sec = (pgp_key_t){0};
} else if (jsoprimary && !jsosub) { // generating primary only
keygen_desc.primary.keygen.crypto.rng = &ffi->rng;
if (!parse_keygen_primary(jsoprimary, &keygen_desc)) {
@ -3870,7 +3894,6 @@ rnp_generate_key_json(rnp_ffi_t ffi, const char *json, char **results)
ret = RNP_ERROR_OUT_OF_MEMORY;
goto done;
}
primary_pub = (pgp_key_t){0};
}
/* encrypt secret key if specified */
if (keygen_desc.primary.protection.symm_alg &&
@ -3886,7 +3909,6 @@ rnp_generate_key_json(rnp_ffi_t ffi, const char *json, char **results)
ret = RNP_ERROR_OUT_OF_MEMORY;
goto done;
}
primary_sec = (pgp_key_t){0};
} else if (jsosub) { // generating subkey only
if (!ffi->pubring) {
ret = RNP_ERROR_NULL_POINTER;
@ -3951,7 +3973,6 @@ rnp_generate_key_json(rnp_ffi_t ffi, const char *json, char **results)
ret = RNP_ERROR_OUT_OF_MEMORY;
goto done;
}
sub_pub = (pgp_key_t){0};
}
/* encrypt subkey if specified */
if (keygen_desc.subkey.protection.symm_alg &&
@ -3967,7 +3988,6 @@ rnp_generate_key_json(rnp_ffi_t ffi, const char *json, char **results)
ret = RNP_ERROR_OUT_OF_MEMORY;
goto done;
}
sub_sec = (pgp_key_t){0};
} else {
// nothing to generate...
ret = RNP_ERROR_BAD_PARAMETERS;
@ -3976,10 +3996,6 @@ rnp_generate_key_json(rnp_ffi_t ffi, const char *json, char **results)
ret = RNP_SUCCESS;
done:
pgp_key_free_data(&primary_pub);
pgp_key_free_data(&primary_sec);
pgp_key_free_data(&sub_pub);
pgp_key_free_data(&sub_sec);
json_object_put(jso);
free(identifier_type);
free(identifier);
@ -4628,7 +4644,6 @@ rnp_op_generate_execute(rnp_op_generate_t op)
ret = RNP_ERROR_OUT_OF_MEMORY;
goto done;
}
pub = {};
/* encrypt secret key if requested */
if (op->password) {
@ -4648,7 +4663,6 @@ rnp_op_generate_execute(rnp_op_generate_t op)
ret = RNP_ERROR_OUT_OF_MEMORY;
goto done;
}
sec = {};
ret = RNP_SUCCESS;
done:
if (op->password) {
@ -4657,17 +4671,13 @@ done:
op->password = NULL;
}
if (ret && op->gen_pub) {
pgp_key_free_data(op->gen_pub);
rnp_key_store_remove_key(op->ffi->pubring, op->gen_pub);
op->gen_pub = NULL;
}
if (ret && op->gen_sec) {
pgp_key_free_data(op->gen_sec);
rnp_key_store_remove_key(op->ffi->secring, op->gen_sec);
op->gen_sec = NULL;
}
pgp_key_free_data(&sec);
pgp_key_free_data(&pub);
return ret;
}
@ -5172,7 +5182,7 @@ rnp_uid_is_revoked(rnp_uid_handle_t uid, bool *result)
return RNP_ERROR_BAD_PARAMETERS;
}
pgp_revoke_t *revoke = pgp_key_get_userid_revoke(uid->key, uid->idx);
const pgp_revoke_t *revoke = pgp_key_get_userid_revoke(uid->key, uid->idx);
*result = revoke != NULL;
return RNP_SUCCESS;
}
@ -5441,6 +5451,49 @@ rnp_key_get_expiration(rnp_key_handle_t handle, uint32_t *result)
return RNP_SUCCESS;
}
rnp_result_t
rnp_key_set_expiration(rnp_key_handle_t key, uint32_t expiry)
{
if (!key) {
return RNP_ERROR_NULL_POINTER;
}
pgp_key_t *pkey = get_key_prefer_public(key);
if (!pkey) {
return RNP_ERROR_BAD_PARAMETERS;
}
pgp_key_t *skey = get_key_require_secret(key);
if (!skey) {
FFI_LOG(key->ffi, "Secret key required.");
return RNP_ERROR_BAD_PARAMETERS;
}
if (pgp_key_is_primary_key(pkey)) {
bool res = pgp_key_set_expiration(pkey, skey, expiry);
return res ? RNP_SUCCESS : RNP_ERROR_GENERIC;
}
/* for subkey we need primary key */
const uint8_t *grip = pgp_key_get_primary_grip(pkey);
if (!grip) {
FFI_LOG(key->ffi, "Primary key grip not available.");
return RNP_ERROR_BAD_PARAMETERS;
}
pgp_key_request_ctx_t request = {};
request.secret = true;
request.search.type = PGP_KEY_SEARCH_GRIP;
memcpy(request.search.by.grip, grip, PGP_KEY_GRIP_SIZE);
pgp_key_t *prim_sec = pgp_request_key(&key->ffi->key_provider, &request);
if (!prim_sec) {
FFI_LOG(key->ffi, "Primary secret key not found.");
return RNP_ERROR_KEY_NOT_FOUND;
}
bool res = pgp_subkey_set_expiration(pkey, prim_sec, skey, expiry);
return res ? RNP_SUCCESS : RNP_ERROR_GENERIC;
}
rnp_result_t
rnp_key_get_revocation_reason(rnp_key_handle_t handle, char **result)
{
@ -6233,7 +6286,7 @@ key_to_json(json_object *jso, rnp_key_handle_t handle, uint32_t flags)
return RNP_ERROR_OUT_OF_MEMORY;
}
// revoked
json_object *jsorevoked = json_object_new_boolean(key->revoked ? TRUE : FALSE);
json_object *jsorevoked = json_object_new_boolean(key->revoked ? true : false);
if (!jsorevoked) {
return RNP_ERROR_OUT_OF_MEMORY;
}
@ -6298,7 +6351,7 @@ key_to_json(json_object *jso, rnp_key_handle_t handle, uint32_t flags)
}
json_object_object_add(jso, "public key", jsopublic);
json_object_object_add(
jsopublic, "present", json_object_new_boolean(have_pub ? TRUE : FALSE));
jsopublic, "present", json_object_new_boolean(have_pub ? true : false));
if (flags & RNP_JSON_PUBLIC_MPIS) {
json_object *jsompis = json_object_new_object();
if (!jsompis) {
@ -6317,7 +6370,7 @@ key_to_json(json_object *jso, rnp_key_handle_t handle, uint32_t flags)
}
json_object_object_add(jso, "secret key", jsosecret);
json_object_object_add(
jsosecret, "present", json_object_new_boolean(have_sec ? TRUE : FALSE));
jsosecret, "present", json_object_new_boolean(have_sec ? true : false));
if (have_sec) {
bool locked = pgp_key_is_locked(handle->sec);
if (flags & RNP_JSON_SECRET_MPIS) {
@ -6335,13 +6388,13 @@ key_to_json(json_object *jso, rnp_key_handle_t handle, uint32_t flags)
}
}
}
json_object *jsolocked = json_object_new_boolean(locked ? TRUE : FALSE);
json_object *jsolocked = json_object_new_boolean(locked ? true : false);
if (!jsolocked) {
return RNP_ERROR_OUT_OF_MEMORY;
}
json_object_object_add(jsosecret, "locked", jsolocked);
json_object *jsoprotected =
json_object_new_boolean(pgp_key_is_protected(handle->sec) ? TRUE : FALSE);
json_object_new_boolean(pgp_key_is_protected(handle->sec) ? true : false);
if (!jsoprotected) {
return RNP_ERROR_OUT_OF_MEMORY;
}
@ -6658,7 +6711,7 @@ key_iter_get_item(const rnp_identifier_iterator_t it, char *buf, size_t buf_len)
}
break;
case PGP_KEY_SEARCH_USERID: {
pgp_userid_t *uid = pgp_key_get_userid(key, it->uididx);
const pgp_userid_t *uid = pgp_key_get_userid(key, it->uididx);
if (!uid) {
return false;
}

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

@ -378,6 +378,8 @@ typedef struct pgp_subsig_t {
uint8_t trustamount; /* amount of trust */
uint8_t key_flags; /* key flags for certification/direct key sig */
pgp_user_prefs_t prefs; /* user preferences for certification sig */
bool validated; /* signature was validated */
bool valid; /* signature was validated and is valid */
} pgp_subsig_t;
typedef struct pgp_userid_t {

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

@ -28,9 +28,9 @@
#define RNP_VERSION_PATCH 1
#define RNP_VERSION_STRING "0.13.1"
#define RNP_VERSION_STRING_FULL "0.13.1+git20200402.5f41ee12.MZLA"
#define RNP_VERSION_STRING_FULL "0.13.1+git20200506.eabaa5d0.MZLA"
#define RNP_VERSION_COMMIT_TIMESTAMP 1585833163
#define RNP_VERSION_COMMIT_TIMESTAMP 1588776848
// using a 32-bit version with 10 bits per component
#define RNP_VERSION_COMPONENT_MASK 0x3ff

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

@ -1104,7 +1104,7 @@ rnp_key_store_g10_from_src(rnp_key_store_t * key_store,
const pgp_key_provider_t *key_provider)
{
const pgp_key_t *pubkey = NULL;
pgp_key_t key = {0};
pgp_key_t key = {};
pgp_key_pkt_t seckey = {};
pgp_source_t memsrc = {};
bool ret = false;
@ -1168,7 +1168,6 @@ done:
src_close(&memsrc);
if (!ret) {
free_key_pkt(&seckey);
pgp_key_free_data(&key);
}
return ret;
}

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

@ -67,100 +67,23 @@ __RCSID("$NetBSD: keyring.c,v 1.50 2011/06/25 00:37:44 agc Exp $");
#include "key_store_pgp.h"
#include "pgp-key.h"
static pgp_map_t ss_rr_code_map[] = {
{PGP_REVOCATION_NO_REASON, "No reason specified"},
{PGP_REVOCATION_SUPERSEDED, "Key is superseded"},
{PGP_REVOCATION_COMPROMISED, "Key material has been compromised"},
{PGP_REVOCATION_RETIRED, "Key is retired and no longer used"},
{PGP_REVOCATION_NO_LONGER_VALID, "User ID information is no longer valid"},
{0x00, NULL}, /* this is the end-of-array marker */
};
bool
rnp_key_add_signature(pgp_key_t *key, const pgp_signature_t *sig)
{
pgp_subsig_t *subsig = NULL;
uint8_t * algs = NULL;
size_t count = 0;
if (!(subsig = pgp_key_add_subsig(key))) {
pgp_subsig_t *subsig = pgp_key_add_subsig(key);
if (!subsig) {
RNP_LOG("Failed to add subsig");
return false;
}
/* add signature rawpacket */
if (!pgp_key_add_sig_rawpacket(key, sig)) {
return false;
}
/* setup subsig and key from signature */
if (!pgp_subsig_from_signature(subsig, sig)) {
return false;
}
subsig->uid = pgp_key_get_userid_count(key) - 1;
if (!copy_signature_packet(&subsig->sig, sig)) {
return false;
}
if (signature_has_key_expiration(&subsig->sig)) {
key->expiration = signature_get_key_expiration(&subsig->sig);
}
if (signature_has_trust(&subsig->sig)) {
signature_get_trust(&subsig->sig, &subsig->trustlevel, &subsig->trustamount);
}
if (signature_get_primary_uid(&subsig->sig)) {
key->uid0 = pgp_key_get_userid_count(key) - 1;
key->uid0_set = 1;
}
if (signature_get_preferred_symm_algs(&subsig->sig, &algs, &count) &&
!pgp_user_prefs_set_symm_algs(&subsig->prefs, algs, count)) {
RNP_LOG("failed to alloc symm algs");
return false;
}
if (signature_get_preferred_hash_algs(&subsig->sig, &algs, &count) &&
!pgp_user_prefs_set_hash_algs(&subsig->prefs, algs, count)) {
RNP_LOG("failed to alloc hash algs");
return false;
}
if (signature_get_preferred_z_algs(&subsig->sig, &algs, &count) &&
!pgp_user_prefs_set_z_algs(&subsig->prefs, algs, count)) {
RNP_LOG("failed to alloc z algs");
return false;
}
if (signature_has_key_flags(&subsig->sig)) {
subsig->key_flags = signature_get_key_flags(&subsig->sig);
key->key_flags = subsig->key_flags;
}
if (signature_has_key_server_prefs(&subsig->sig)) {
uint8_t ks_pref = signature_get_key_server_prefs(&subsig->sig);
if (!pgp_user_prefs_set_ks_prefs(&subsig->prefs, &ks_pref, 1)) {
RNP_LOG("failed to alloc ks prefs");
return false;
}
}
if (signature_has_key_server(&subsig->sig)) {
subsig->prefs.key_server = (uint8_t *) signature_get_key_server(&subsig->sig);
}
if (signature_has_revocation_reason(&subsig->sig)) {
/* not sure whether this logic is correct - we should check signature type? */
pgp_revoke_t *revocation = NULL;
if (!pgp_key_get_userid_count(key)) {
/* revoke whole key */
key->revoked = 1;
revocation = &key->revocation;
revoke_free(revocation);
} else {
/* revoke the user id */
if (!(revocation = pgp_key_add_revoke(key))) {
RNP_LOG("failed to add revoke");
return false;
}
revocation->uid = pgp_key_get_userid_count(key) - 1;
}
signature_get_revocation_reason(&subsig->sig, &revocation->code, &revocation->reason);
if (!strlen(revocation->reason)) {
free(revocation->reason);
revocation->reason = strdup(pgp_str_from_map(revocation->code, ss_rr_code_map));
}
}
return true;
}
@ -189,15 +112,11 @@ rnp_key_store_add_transferable_subkey(rnp_key_store_t * keyring,
}
/* add it to the storage */
if (!rnp_key_store_add_key(keyring, &skey)) {
bool res = rnp_key_store_add_key(keyring, &skey);
if (!res) {
RNP_LOG("Failed to add subkey to key store.");
goto error;
}
return true;
error:
pgp_key_free_data(&skey);
return false;
return res;
}
bool
@ -252,36 +171,39 @@ rnp_key_store_add_transferable_key(rnp_key_store_t *keyring, pgp_transferable_ke
return false;
}
/* temporary disable key validation */
keyring->disable_validation = true;
/* add key to the storage before subkeys */
if (!(addkey = rnp_key_store_add_key(keyring, &key))) {
addkey = rnp_key_store_add_key(keyring, &key);
if (!addkey) {
RNP_LOG("Failed to add key to key store.");
goto error;
return false;
}
/* add subkeys */
for (list_item *skey = list_front(tkey->subkeys); skey; skey = list_next(skey)) {
pgp_transferable_subkey_t *subkey = (pgp_transferable_subkey_t *) skey;
if (!rnp_key_store_add_transferable_subkey(keyring, subkey, addkey)) {
RNP_LOG("Failed to add subkey to key store.");
goto error;
}
}
/* now validate/refresh the whole key with subkeys */
keyring->disable_validation = false;
pgp_key_revalidate_updated(addkey, keyring);
return true;
error:
if (addkey) {
/* during key addition all fields are copied so will be cleaned below */
rnp_key_store_remove_key(keyring, addkey);
pgp_key_free_data(addkey);
} else {
pgp_key_free_data(&key);
}
return false;
}
bool
rnp_key_from_transferable_key(pgp_key_t *key, pgp_transferable_key_t *tkey)
{
memset(key, 0, sizeof(*key));
*key = {};
/* create key */
if (!pgp_key_from_pkt(key, &tkey->key)) {
return false;
@ -289,21 +211,18 @@ rnp_key_from_transferable_key(pgp_key_t *key, pgp_transferable_key_t *tkey)
/* add direct-key signatures */
if (!rnp_key_add_signatures(key, tkey->signatures)) {
goto error;
return false;
}
/* add userids and their signatures */
for (list_item *uid = list_front(tkey->userids); uid; uid = list_next(uid)) {
pgp_transferable_userid_t *tuid = (pgp_transferable_userid_t *) uid;
if (!rnp_key_add_transferable_userid(key, tuid)) {
goto error;
return false;
}
}
return true;
error:
pgp_key_free_data(key);
return false;
}
bool
@ -311,7 +230,7 @@ rnp_key_from_transferable_subkey(pgp_key_t * subkey,
pgp_transferable_subkey_t *tskey,
pgp_key_t * primary)
{
memset(subkey, 0, sizeof(*subkey));
*subkey = {};
/* create key */
if (!pgp_key_from_pkt(subkey, &tskey->subkey)) {
@ -321,17 +240,15 @@ rnp_key_from_transferable_subkey(pgp_key_t * subkey,
/* add subkey binding signatures */
if (!rnp_key_add_signatures(subkey, tskey->signatures)) {
RNP_LOG("failed to add subkey signatures");
goto error;
return false;
}
/* setup key grips if primary is available */
if (primary && !pgp_key_link_subkey_grip(primary, subkey)) {
goto error;
}
return true;
error:
pgp_key_free_data(subkey);
return false;
}
return true;
}
rnp_result_t
@ -378,7 +295,7 @@ rnp_key_write_packets_stream(const pgp_key_t *key, pgp_dest_t *dst)
return false;
}
for (size_t i = 0; i < pgp_key_get_rawpacket_count(key); i++) {
pgp_rawpacket_t *pkt = pgp_key_get_rawpacket(key, i);
const pgp_rawpacket_t *pkt = pgp_key_get_rawpacket(key, i);
if (!pkt->raw || !pkt->length) {
return false;
}

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

@ -244,7 +244,7 @@ void
rnp_key_store_clear(rnp_key_store_t *keyring)
{
for (list_item *key = list_front(keyring->keys); key; key = list_next(key)) {
pgp_key_free_data((pgp_key_t *) key);
((pgp_key_t *) key)->~pgp_key_t();
}
list_destroy(&keyring->keys);
@ -338,9 +338,14 @@ rnp_key_store_merge_subkey(pgp_key_t *dst, const pgp_key_t *src, pgp_key_t *prim
} else if (pgp_key_is_secret(src) && !pgp_key_is_locked(src)) {
tmpkey.pkt.material = src->pkt.material;
}
/* copy validity status */
tmpkey.valid = dst->valid && src->valid;
/* we may safely leave validated status only if both merged subkeys are valid && validated.
* Otherwise we'll need to revalidate. For instance, one validated but invalid subkey may
* add revocation signature, or valid subkey may add binding to the invalid one. */
tmpkey.validated = dst->validated && src->validated && tmpkey.valid;
pgp_key_free_data(dst);
*dst = tmpkey;
*dst = std::move(tmpkey);
res = true;
done:
transferable_subkey_destroy(&dstkey);
@ -406,9 +411,14 @@ rnp_key_store_merge_key(pgp_key_t *dst, const pgp_key_t *src)
} else if (pgp_key_is_secret(src) && !pgp_key_is_locked(src)) {
tmpkey.pkt.material = src->pkt.material;
}
/* copy validity status */
tmpkey.valid = dst->valid && src->valid;
/* We may safely leave validated status only if both merged keys are valid && validated.
* Otherwise we'll need to revalidate. For instance, one validated but invalid key may add
* revocation signature, or valid key may add certification to the invalid one. */
tmpkey.validated = dst->validated && src->validated && tmpkey.valid;
pgp_key_free_data(dst);
*dst = tmpkey;
*dst = std::move(tmpkey);
res = true;
done:
transferable_key_destroy(&dstkey);
@ -437,7 +447,7 @@ rnp_key_store_refresh_subkey_grips(rnp_key_store_t *keyring, pgp_key_t *key)
}
for (unsigned i = 0; i < pgp_key_get_subsig_count(skey); i++) {
pgp_subsig_t *subsig = pgp_key_get_subsig(skey, i);
const pgp_subsig_t *subsig = pgp_key_get_subsig(skey, i);
if (subsig->sig.type != PGP_SIG_SUBKEY) {
continue;
@ -464,76 +474,91 @@ rnp_key_store_refresh_subkey_grips(rnp_key_store_t *keyring, pgp_key_t *key)
return true;
}
/* add a key to keyring */
pgp_key_t *
rnp_key_store_add_key(rnp_key_store_t *keyring, pgp_key_t *srckey)
static pgp_key_t *
rnp_key_store_add_subkey(rnp_key_store_t *keyring, pgp_key_t *srckey, pgp_key_t *oldkey)
{
pgp_key_t *added_key = NULL;
RNP_DLOG("rnp_key_store_add_key");
assert(pgp_key_get_type(srckey) && pgp_key_get_version(srckey));
added_key = rnp_key_store_get_key_by_grip(keyring, pgp_key_get_grip(srckey));
if (added_key) {
/* we cannot merge G10 keys - so just return it */
if (srckey->format == PGP_KEY_STORE_G10) {
pgp_key_free_data(srckey);
return added_key;
pgp_key_t *primary = rnp_key_store_get_primary_key(keyring, srckey);
if (!primary && oldkey) {
primary = rnp_key_store_get_primary_key(keyring, oldkey);
}
bool mergeres = false;
if (oldkey) {
/* in case we already have key let's merge it in */
if (pgp_key_is_subkey(added_key)) {
pgp_key_t *primary = rnp_key_store_get_primary_key(keyring, added_key);
if (!primary) {
primary = rnp_key_store_get_primary_key(keyring, srckey);
}
if (!primary) {
RNP_LOG("no primary key for subkey");
}
mergeres = rnp_key_store_merge_subkey(added_key, srckey, primary);
} else {
mergeres = rnp_key_store_merge_key(added_key, srckey);
}
if (!mergeres) {
RNP_LOG("failed to merge key or subkey");
if (!rnp_key_store_merge_subkey(oldkey, srckey, primary)) {
RNP_LOG("failed to merge subkey");
return NULL;
}
added_key->valid = added_key->valid && srckey->valid;
added_key->validated = added_key->validated && srckey->validated && added_key->valid;
pgp_key_free_data(srckey);
} else {
added_key = (pgp_key_t *) list_append(&keyring->keys, srckey, sizeof(*srckey));
if (!added_key) {
oldkey = (pgp_key_t *) list_append(&keyring->keys, NULL, sizeof(*srckey));
if (!oldkey) {
RNP_LOG("allocation failed");
return NULL;
}
/* primary key may be added after subkeys, so let's handle this case correctly */
if (pgp_key_is_primary_key(added_key) &&
!rnp_key_store_refresh_subkey_grips(keyring, added_key)) {
RNP_LOG("failed to refresh subkey grips");
if (pgp_key_copy(oldkey, srckey, false)) {
RNP_LOG("key copying failed");
list_remove((list_item *) oldkey);
return NULL;
}
if (primary && !pgp_key_link_subkey_grip(primary, oldkey)) {
RNP_LOG("failed to link subkey grip");
}
}
RNP_DLOG("keyc %lu", (long unsigned) rnp_key_store_get_key_count(keyring));
/* validate all added keys if not disabled */
if (!keyring->disable_validation && !oldkey->validated) {
pgp_key_validate_subkey(oldkey, primary);
}
if (!pgp_subkey_refresh_data(oldkey, primary)) {
RNP_LOG("Failed to refresh subkey data");
}
return oldkey;
}
/* add a key to keyring */
pgp_key_t *
rnp_key_store_add_key(rnp_key_store_t *keyring, pgp_key_t *srckey)
{
assert(pgp_key_get_type(srckey) && pgp_key_get_version(srckey));
pgp_key_t *added_key = rnp_key_store_get_key_by_grip(keyring, pgp_key_get_grip(srckey));
/* we cannot merge G10 keys - so just return it */
if (added_key && (srckey->format == PGP_KEY_STORE_G10)) {
return added_key;
}
/* different processing for subkeys */
if (pgp_key_is_subkey(srckey)) {
return rnp_key_store_add_subkey(keyring, srckey, added_key);
}
if (added_key) {
if (!rnp_key_store_merge_key(added_key, srckey)) {
RNP_LOG("failed to merge key");
return NULL;
}
} else {
added_key = (pgp_key_t *) list_append(&keyring->keys, NULL, sizeof(*srckey));
if (!added_key) {
RNP_LOG("allocation failed");
return NULL;
}
if (pgp_key_copy(added_key, srckey, false)) {
RNP_LOG("key copying failed");
list_remove((list_item *) added_key);
return NULL;
}
/* primary key may be added after subkeys, so let's handle this case correctly */
if (!rnp_key_store_refresh_subkey_grips(keyring, added_key)) {
RNP_LOG("failed to refresh subkey grips");
}
}
RNP_DLOG("keyc %lu", (long unsigned) rnp_key_store_get_key_count(keyring));
/* validate all added keys if not disabled or already validated */
if (!keyring->disable_validation && !added_key->validated) {
pgp_key_validate(added_key, keyring);
/* validate/re-validate all subkeys as well */
if (pgp_key_is_primary_key(added_key)) {
for (list_item *grip = list_front(added_key->subkey_grips); grip;
grip = list_next(grip)) {
pgp_key_t *subkey = rnp_key_store_get_key_by_grip(keyring, (uint8_t *) grip);
if (subkey) {
pgp_key_validate(subkey, keyring);
pgp_key_revalidate_updated(added_key, keyring);
} else if (!pgp_key_refresh_data(added_key)) {
RNP_LOG("Failed to refresh key data");
}
}
}
}
return added_key;
}
@ -555,13 +580,18 @@ rnp_key_store_import_key(rnp_key_store_t * keyring,
}
exkey = rnp_key_store_get_key_by_grip(keyring, pgp_key_get_grip(srckey));
expackets = exkey ? pgp_key_get_rawpacket_count(exkey) : 0;
if (!(exkey = rnp_key_store_add_key(keyring, &keycp))) {
keyring->disable_validation = true;
exkey = rnp_key_store_add_key(keyring, &keycp);
keyring->disable_validation = false;
if (!exkey) {
RNP_LOG("failed to add key to the keyring");
pgp_key_free_data(&keycp);
return NULL;
}
changed = pgp_key_get_rawpacket_count(exkey) > expackets;
if (changed) {
/* this will revalidated primary key with all subkeys */
pgp_key_revalidate_updated(exkey, keyring);
}
if (status) {
*status = changed ?
(expackets ? PGP_KEY_IMPORT_STATUS_UPDATED : PGP_KEY_IMPORT_STATUS_NEW) :
@ -588,43 +618,97 @@ rnp_key_store_get_signer_key(rnp_key_store_t *store, const pgp_signature_t *sig)
return NULL;
}
static pgp_sig_import_status_t
rnp_key_store_import_subkey_signature(rnp_key_store_t * keyring,
pgp_key_t * key,
const pgp_signature_t *sig)
{
pgp_sig_type_t sigtype = signature_get_type(sig);
if ((sigtype != PGP_SIG_SUBKEY) && (sigtype != PGP_SIG_REV_SUBKEY)) {
return PGP_SIG_IMPORT_STATUS_UNKNOWN;
}
const uint8_t *prim_grip = pgp_key_get_primary_grip(key);
pgp_key_t * primary = rnp_key_store_get_signer_key(keyring, sig);
if (!prim_grip || !primary) {
RNP_LOG("No primary grip or primary key");
return PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY;
}
if (memcmp(pgp_key_get_grip(primary), prim_grip, PGP_KEY_GRIP_SIZE)) {
RNP_LOG("Wrong subkey signature's signer.");
return PGP_SIG_IMPORT_STATUS_UNKNOWN;
}
pgp_key_t tmpkey = {};
if (!pgp_key_from_pkt(&tmpkey, &key->pkt) || !rnp_key_add_signature(&tmpkey, sig) ||
!pgp_subkey_refresh_data(&tmpkey, primary)) {
RNP_LOG("Failed to add signature to the key.");
return PGP_SIG_IMPORT_STATUS_UNKNOWN;
}
size_t expackets = pgp_key_get_rawpacket_count(key);
key = rnp_key_store_add_key(keyring, &tmpkey);
if (!key) {
RNP_LOG("Failed to add key with imported sig to the keyring");
return PGP_SIG_IMPORT_STATUS_UNKNOWN;
}
return (pgp_key_get_rawpacket_count(key) > expackets) ? PGP_SIG_IMPORT_STATUS_NEW :
PGP_SIG_IMPORT_STATUS_UNCHANGED;
}
pgp_sig_import_status_t
rnp_key_store_import_key_signature(rnp_key_store_t * keyring,
pgp_key_t * key,
const pgp_signature_t *sig)
{
if (pgp_key_is_subkey(key)) {
return rnp_key_store_import_subkey_signature(keyring, key, sig);
}
pgp_sig_type_t sigtype = signature_get_type(sig);
if ((sigtype != PGP_SIG_DIRECT) && (sigtype != PGP_SIG_REV_KEY)) {
RNP_LOG("Wrong signature type: %d", (int) sigtype);
return PGP_SIG_IMPORT_STATUS_UNKNOWN;
}
pgp_key_t tmpkey = {};
if (!pgp_key_from_pkt(&tmpkey, &key->pkt) || !rnp_key_add_signature(&tmpkey, sig) ||
!pgp_key_refresh_data(&tmpkey)) {
RNP_LOG("Failed to add signature to the key.");
return PGP_SIG_IMPORT_STATUS_UNKNOWN;
}
size_t expackets = pgp_key_get_rawpacket_count(key);
key = rnp_key_store_add_key(keyring, &tmpkey);
if (!key) {
RNP_LOG("Failed to add key with imported sig to the keyring");
return PGP_SIG_IMPORT_STATUS_UNKNOWN;
}
return (pgp_key_get_rawpacket_count(key) > expackets) ? PGP_SIG_IMPORT_STATUS_NEW :
PGP_SIG_IMPORT_STATUS_UNCHANGED;
}
pgp_key_t *
rnp_key_store_import_signature(rnp_key_store_t * keyring,
const pgp_signature_t * sig,
pgp_sig_import_status_t *status)
{
pgp_key_t * res_key = NULL;
pgp_key_t tmpkey = {};
pgp_sig_import_status_t res_status = PGP_SIG_IMPORT_STATUS_UNKNOWN;
pgp_sig_type_t sigtype = signature_get_type(sig);
size_t expackets = 0;
pgp_sig_import_status_t tmp_status = PGP_SIG_IMPORT_STATUS_UNKNOWN;
if (!status) {
status = &tmp_status;
}
*status = PGP_SIG_IMPORT_STATUS_UNKNOWN;
pgp_sig_type_t sigtype = signature_get_type(sig);
/* we support only direct-key and key revocation signatures here */
if ((sigtype != PGP_SIG_DIRECT) && (sigtype != PGP_SIG_REV_KEY)) {
goto done;
}
res_key = rnp_key_store_get_signer_key(keyring, sig);
if (!res_key) {
res_status = PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY;
goto done;
}
if (!pgp_key_from_pkt(&tmpkey, &res_key->pkt) || !rnp_key_add_signature(&tmpkey, sig)) {
goto done;
return NULL;
}
expackets = pgp_key_get_rawpacket_count(res_key);
if (!(res_key = rnp_key_store_add_key(keyring, &tmpkey))) {
RNP_LOG("failed to add key with imported sig to the keyring");
goto done;
}
res_status = (pgp_key_get_rawpacket_count(res_key) > expackets) ?
PGP_SIG_IMPORT_STATUS_NEW :
PGP_SIG_IMPORT_STATUS_UNCHANGED;
done:
pgp_key_free_data(&tmpkey);
if (status) {
*status = res_status;
pgp_key_t *res_key = rnp_key_store_get_signer_key(keyring, sig);
if (!res_key || !pgp_key_is_primary_key(res_key)) {
*status = PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY;
return NULL;
}
*status = rnp_key_store_import_key_signature(keyring, res_key, sig);
return res_key;
}
@ -635,6 +719,7 @@ rnp_key_store_remove_key(rnp_key_store_t *keyring, const pgp_key_t *key)
if (!list_is_member(keyring->keys, (list_item *) key)) {
return false;
}
key->~pgp_key_t();
list_remove((list_item *) key);
return true;
}
@ -731,7 +816,7 @@ rnp_key_store_get_primary_key(const rnp_key_store_t *keyring, const pgp_key_t *s
}
for (unsigned i = 0; i < pgp_key_get_subsig_count(subkey); i++) {
pgp_subsig_t *subsig = pgp_key_get_subsig(subkey, i);
const pgp_subsig_t *subsig = pgp_key_get_subsig(subkey, i);
if (subsig->sig.type != PGP_SIG_SUBKEY) {
continue;
}

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

@ -937,11 +937,6 @@ init_armored_dst(pgp_dest_t *dst, pgp_dest_t *writedst, pgp_armored_msg_t msgtyp
/* armor header */
dst_write(writedst, hdr, strlen(hdr));
armor_write_eol(param);
/* version string */
strncpy(hdr, "Version: " PACKAGE_STRING, sizeof(hdr));
hdr[sizeof(hdr) - 1] = '\0';
dst_write(writedst, hdr, strlen(hdr));
armor_write_eol(param);
/* empty line */
armor_write_eol(param);

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

@ -52,6 +52,10 @@ src_read(pgp_source_t *src, void *buf, size_t len, size_t *readres)
pgp_source_cache_t *cache = src->cache;
bool readahead = cache ? cache->readahead : false;
if (src->error) {
return false;
}
if (src->eof || (len == 0)) {
*readres = 0;
return true;
@ -137,6 +141,9 @@ bool
src_peek(pgp_source_t *src, void *buf, size_t len, size_t *peeked)
{
pgp_source_cache_t *cache = src->cache;
if (src->error) {
return false;
}
if (!cache || (len > sizeof(cache->buf))) {
return false;
}
@ -220,6 +227,7 @@ src_skip(pgp_source_t *src, size_t len)
void *buf = calloc(1, std::min((size_t) PGP_INPUT_CACHE_SIZE, len));
if (!buf) {
src->error = 1;
return;
}

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

@ -353,6 +353,54 @@ transferable_key_add_userid(pgp_transferable_key_t *key, const char *userid)
return tuid;
}
bool
signature_calculate_certification(const pgp_key_pkt_t * key,
const pgp_userid_pkt_t *uid,
pgp_signature_t * sig,
const pgp_key_pkt_t * signer)
{
if (!key || !uid || !sig || !signer) {
RNP_LOG("NULL parameter(s)");
return false;
}
rng_t rng = {};
if (!rng_init(&rng, RNG_SYSTEM)) {
RNP_LOG("RNG init failed");
return false;
}
pgp_hash_t hash = {};
bool res = signature_fill_hashed_data(sig) &&
signature_hash_certification(sig, key, uid, &hash) &&
!signature_calculate(sig, &signer->material, &hash, &rng);
rng_destroy(&rng);
return res;
}
bool
signature_calculate_direct(const pgp_key_pkt_t *key,
pgp_signature_t * sig,
const pgp_key_pkt_t *signer)
{
if (!key || !sig || !signer) {
RNP_LOG("NULL parameter(s)");
return false;
}
rng_t rng = {};
if (!rng_init(&rng, RNG_SYSTEM)) {
RNP_LOG("RNG init failed");
return false;
}
pgp_hash_t hash = {};
bool res = signature_fill_hashed_data(sig) && signature_hash_direct(sig, key, &hash) &&
!signature_calculate(sig, &signer->material, &hash, &rng);
rng_destroy(&rng);
return res;
}
pgp_signature_t *
transferable_userid_certify(const pgp_key_pkt_t * key,
pgp_transferable_userid_t * userid,
@ -362,10 +410,8 @@ transferable_userid_certify(const pgp_key_pkt_t * key,
{
pgp_signature_t sig = {};
pgp_signature_t * res = NULL;
pgp_hash_t hash = {};
uint8_t keyid[PGP_KEY_ID_SIZE];
pgp_fingerprint_t keyfp;
rng_t rng = {};
const pgp_user_prefs_t *prefs = NULL;
if (!key || !userid || !signer || !cert) {
@ -373,11 +419,6 @@ transferable_userid_certify(const pgp_key_pkt_t * key,
return NULL;
}
if (!rng_init(&rng, RNG_SYSTEM)) {
RNP_LOG("RNG init failed");
return NULL;
}
if (pgp_keyid(keyid, sizeof(keyid), signer)) {
RNP_LOG("failed to calculate keyid");
goto end;
@ -446,31 +487,20 @@ transferable_userid_certify(const pgp_key_pkt_t * key,
goto end;
}
if (!signature_fill_hashed_data(&sig) ||
!signature_hash_certification(&sig, key, &userid->uid, &hash) ||
signature_calculate(&sig, &signer->material, &hash, &rng)) {
if (!signature_calculate_certification(key, &userid->uid, &sig, signer)) {
RNP_LOG("failed to calculate signature");
goto end;
}
res = (pgp_signature_t *) list_append(&userid->signatures, &sig, sizeof(sig));
end:
rng_destroy(&rng);
if (!res) {
free_signature(&sig);
}
return res;
}
bool calculate_primary_binding(const pgp_key_pkt_t *key,
const pgp_key_pkt_t *subkey,
pgp_hash_alg_t halg,
pgp_signature_t * sig,
pgp_hash_t * hash,
rng_t * rng);
bool
calculate_primary_binding(const pgp_key_pkt_t *key,
static bool
signature_calculate_primary_binding(const pgp_key_pkt_t *key,
const pgp_key_pkt_t *subkey,
pgp_hash_alg_t halg,
pgp_signature_t * sig,
@ -514,40 +544,90 @@ end:
return res;
}
bool
signature_calculate_binding(const pgp_key_pkt_t *key,
const pgp_key_pkt_t *sub,
pgp_signature_t * sig,
bool subsign)
{
pgp_hash_t hash = {};
pgp_hash_t hashcp = {};
rng_t rng = {};
uint8_t keyid[PGP_KEY_ID_SIZE];
if (pgp_keyid(keyid, sizeof(keyid), key)) {
RNP_LOG("failed to calculate keyid");
return false;
}
if (!rng_init(&rng, RNG_SYSTEM)) {
RNP_LOG("RNG init failed");
return false;
}
bool res = false;
if (!signature_fill_hashed_data(sig) || !signature_hash_binding(sig, key, sub, &hash) ||
!pgp_hash_copy(&hashcp, &hash)) {
RNP_LOG("failed to hash signature");
goto end;
}
if (signature_calculate(sig, &key->material, &hash, &rng)) {
RNP_LOG("failed to calculate signature");
goto end;
}
/* unhashed subpackets. Primary key binding signature and issuer key id */
if (subsign) {
pgp_signature_t embsig = {};
bool embres;
if (!signature_calculate_primary_binding(
key, sub, sig->halg, &embsig, &hashcp, &rng)) {
RNP_LOG("failed to calculate primary key binding signature");
goto end;
}
embres = signature_set_embedded_sig(sig, &embsig);
free_signature(&embsig);
if (!embres) {
RNP_LOG("failed to add primary key binding signature");
goto end;
}
}
/* add keyid since it should (probably) be after the primary key binding if any */
if (!signature_set_keyid(sig, keyid)) {
RNP_LOG("failed to set issuer key id");
goto end;
}
res = true;
end:
pgp_hash_finish(&hashcp, NULL);
rng_destroy(&rng);
return res;
}
pgp_signature_t *
transferable_subkey_bind(const pgp_key_pkt_t * key,
pgp_transferable_subkey_t * subkey,
pgp_hash_alg_t hash_alg,
const rnp_selfsig_binding_info_t *binding)
{
pgp_signature_t sig = {};
pgp_signature_t * res = NULL;
pgp_hash_t hash = {};
pgp_hash_t hashcp = {};
pgp_key_flags_t realkf = (pgp_key_flags_t) 0;
uint8_t keyid[PGP_KEY_ID_SIZE];
pgp_fingerprint_t keyfp;
rng_t rng = {};
if (!key || !subkey || !binding) {
RNP_LOG("invalid parameters");
return NULL;
}
if (!rng_init(&rng, RNG_SYSTEM)) {
RNP_LOG("RNG init failed");
pgp_fingerprint_t keyfp;
if (pgp_fingerprint(&keyfp, key)) {
RNP_LOG("failed to calculate keyfp");
return NULL;
}
if (pgp_keyid(keyid, sizeof(keyid), key)) {
RNP_LOG("failed to calculate keyid");
goto end;
}
if (pgp_fingerprint(&keyfp, key)) {
RNP_LOG("failed to calculate keyfp");
goto end;
}
pgp_signature_t sig = {};
pgp_signature_t *res = NULL;
pgp_key_flags_t realkf = (pgp_key_flags_t) 0;
sig.version = PGP_V4;
sig.halg = pgp_hash_adjust_alg_to_key(hash_alg, key);
@ -572,49 +652,17 @@ transferable_subkey_bind(const pgp_key_pkt_t * key,
goto end;
}
if (!signature_fill_hashed_data(&sig) ||
!signature_hash_binding(&sig, key, &subkey->subkey, &hash) ||
!pgp_hash_copy(&hashcp, &hash)) {
RNP_LOG("failed to hash signature");
goto end;
}
if (signature_calculate(&sig, &key->material, &hash, &rng)) {
RNP_LOG("failed to calculate signature");
goto end;
}
/* unhashed subpackets. Primary key binding signature and issuer key id */
realkf = (pgp_key_flags_t) binding->key_flags;
if (!realkf) {
realkf = pgp_pk_alg_capabilities(key->alg);
}
if (realkf & PGP_KF_SIGN) {
pgp_signature_t embsig = {};
bool embres;
if (!calculate_primary_binding(
key, &subkey->subkey, hash_alg, &embsig, &hashcp, &rng)) {
RNP_LOG("failed to calculate primary key binding signature");
goto end;
}
embres = signature_set_embedded_sig(&sig, &embsig);
free_signature(&embsig);
if (!embres) {
RNP_LOG("failed to add primary key binding signature");
goto end;
}
realkf = pgp_pk_alg_capabilities(subkey->subkey.alg);
}
if (!signature_set_keyid(&sig, keyid)) {
RNP_LOG("failed to set issuer key id");
if (!signature_calculate_binding(key, &subkey->subkey, &sig, realkf & PGP_KF_SIGN)) {
goto end;
}
res = (pgp_signature_t *) list_append(&subkey->signatures, &sig, sizeof(sig));
end:
pgp_hash_finish(&hashcp, NULL);
rng_destroy(&rng);
if (!res) {
free_signature(&sig);
}
@ -629,19 +677,13 @@ transferable_key_revoke(const pgp_key_pkt_t *key,
{
pgp_signature_t * sig = NULL;
bool res = false;
pgp_hash_t hash = {};
uint8_t keyid[PGP_KEY_ID_SIZE];
pgp_fingerprint_t keyfp;
rng_t rng = {};
if (!key || !signer || !revoke) {
RNP_LOG("invalid parameters");
return NULL;
}
if (!rng_init(&rng, RNG_SYSTEM)) {
RNP_LOG("RNG init failed");
return NULL;
}
sig = (pgp_signature_t *) calloc(1, sizeof(*sig));
if (!sig) {
RNP_LOG("allocation failed");
@ -678,14 +720,15 @@ transferable_key_revoke(const pgp_key_pkt_t *key,
goto end;
}
if (!signature_fill_hashed_data(sig) || !signature_hash_direct(sig, key, &hash) ||
signature_calculate(sig, &signer->material, &hash, &rng)) {
RNP_LOG("failed to calculate signature");
goto end;
if (is_primary_key_pkt(key->tag)) {
res = signature_calculate_direct(key, sig, signer);
} else {
res = signature_calculate_binding(signer, key, sig, false);
}
if (!res) {
RNP_LOG("failed to calculate signature");
}
res = true;
end:
rng_destroy(&rng);
if (!res && sig) {
free_signature(sig);
free(sig);

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

@ -123,4 +123,18 @@ rnp_result_t encrypt_secret_key(pgp_key_pkt_t *key, const char *password, rng_t
void forget_secret_key_fields(pgp_key_material_t *key);
bool signature_calculate_certification(const pgp_key_pkt_t * key,
const pgp_userid_pkt_t *uid,
pgp_signature_t * sig,
const pgp_key_pkt_t * signer);
bool signature_calculate_direct(const pgp_key_pkt_t *key,
pgp_signature_t * sig,
const pgp_key_pkt_t *signer);
bool signature_calculate_binding(const pgp_key_pkt_t *key,
const pgp_key_pkt_t *sub,
pgp_signature_t * sig,
bool subsign);
#endif

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

@ -637,13 +637,14 @@ encrypted_src_read_cfb(pgp_source_t *src, void *buf, size_t len, size_t *readres
uint8_t mdcbuf[MDC_V1_SIZE];
if (param->has_mdc) {
size_t mdcread = 0;
/* make sure there are always 20 bytes left on input */
/* make sure there are always 22 bytes left on input */
if (!src_peek(param->pkt.readsrc, mdcbuf, MDC_V1_SIZE, &mdcread) ||
(mdcread + read < MDC_V1_SIZE)) {
RNP_LOG("wrong mdc read state");
return false;
}
if (mdcread < MDC_V1_SIZE) {
src_skip(param->pkt.readsrc, mdcread);
size_t mdcsub = MDC_V1_SIZE - mdcread;
memmove(&mdcbuf[mdcsub], mdcbuf, mdcread);
memcpy(mdcbuf, (uint8_t *) buf + read - mdcsub, mdcsub);

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

@ -93,7 +93,7 @@ signature_add_subpkt(pgp_signature_t * sig,
}
if (reuse && (subpkt = signature_get_subpkt(sig, type))) {
free(subpkt->data);
free_signature_subpkt(subpkt);
memset(subpkt, 0, sizeof(*subpkt));
}
@ -110,7 +110,6 @@ signature_add_subpkt(pgp_signature_t * sig,
subpkt->type = type;
subpkt->len = datalen;
return subpkt;
}
@ -871,6 +870,7 @@ signature_fill_hashed_data(pgp_signature_t *sig)
}
if (res) {
free(sig->hashed_data);
/* get ownership on body data */
sig->hashed_data = hbody.data;
sig->hashed_len = hbody.len;
@ -1179,33 +1179,12 @@ signature_check_certification(pgp_signature_info_t * sinfo,
const pgp_userid_pkt_t *uid)
{
pgp_hash_t hash = {};
uint8_t keyid[PGP_KEY_ID_SIZE];
rnp_result_t res = RNP_ERROR_SIGNATURE_INVALID;
if (!signature_hash_certification(sinfo->sig, key, uid, &hash)) {
return RNP_ERROR_BAD_FORMAT;
}
res = signature_check(sinfo, &hash);
if (res) {
return res;
}
/* check key expiration time, only for self-signature. While sinfo->expired tells about
the signature expiry, we'll use it for bkey expiration as well */
if (signature_get_keyid(sinfo->sig, keyid) &&
!memcmp(keyid, pgp_key_get_keyid(sinfo->signer), PGP_KEY_ID_SIZE)) {
uint32_t expiry = signature_get_key_expiration(sinfo->sig);
uint32_t now = time(NULL);
if (expiry && (key->creation_time + expiry < now)) {
RNP_LOG("key expired %d seconds ago", (int) now - expiry - key->creation_time);
sinfo->expired = true;
}
}
return res;
return signature_check(sinfo, &hash);
}
rnp_result_t
@ -1228,19 +1207,6 @@ signature_check_binding(pgp_signature_info_t *sinfo,
res = signature_check(sinfo, &hash);
/* check subkey expiration time. While sinfo->expired tells about the signature expiry,
we'll use it for subkey expiration as well */
if (!res) {
uint32_t expiry = signature_get_key_expiration(sinfo->sig);
uint32_t now = time(NULL);
if (expiry && (subkey->creation_time + expiry < now)) {
RNP_LOG("subkey expired %d seconds ago",
(int) now - expiry - subkey->creation_time);
sinfo->expired = true;
}
}
/* check primary key binding signature if any */
if (!res && (signature_get_key_flags(sinfo->sig) & PGP_KF_SIGN)) {
res = RNP_ERROR_SIGNATURE_INVALID;

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

@ -697,6 +697,7 @@ cli_rnp_print_key_info(FILE *fp, rnp_ffi_t ffi, rnp_key_handle_t key, bool psecr
const char * header = NULL;
bool secret = false;
bool primary = false;
bool revoked = false;
uint32_t bits = 0;
int64_t create = 0;
uint32_t expiry = 0;
@ -712,11 +713,11 @@ cli_rnp_print_key_info(FILE *fp, rnp_ffi_t ffi, rnp_key_handle_t key, bool psecr
return;
}
if (!(pkts = json_tokener_parse(json))) {
fprintf(fp, "Key JSON error");
fprintf(fp, "Key JSON error.\n");
goto done;
}
if (!(keypkt = json_object_array_get_idx(pkts, 0))) {
fprintf(fp, "Key JSON error");
fprintf(fp, "Key JSON error.\n");
goto done;
}
@ -750,6 +751,11 @@ cli_rnp_print_key_info(FILE *fp, rnp_ffi_t ffi, rnp_key_handle_t key, bool psecr
ptimestr(buf, sizeof(buf), expire_time);
fprintf(fp, " [%s %s]", expire_time <= now ? "EXPIRED" : "EXPIRES", buf);
}
/* key is revoked */
(void) rnp_key_is_revoked(key, &revoked);
if (revoked) {
fprintf(fp, " [REVOKED]");
}
/* fingerprint */
fprintf(fp, "\n %s\n", json_obj_get_str(keypkt, "fingerprint"));
/* user ids */
@ -1733,6 +1739,74 @@ done:
return result;
}
bool
cli_rnp_revoke_key(cli_rnp_t *rnp, const char *key)
{
std::vector<rnp_key_handle_t> keys;
if (!cli_rnp_keys_matching_string(rnp, keys, key, CLI_SEARCH_SUBKEYS)) {
ERR_MSG("Key matching '%s' not found.", key);
return false;
}
rnp_cfg_t * cfg = cli_rnp_cfg(rnp);
bool res = false;
bool revoked = false;
rnp_result_t ret = 0;
if (keys.size() > 1) {
ERR_MSG("Ambiguous input: too many keys found for '%s'.", key);
goto done;
}
if (rnp_key_is_revoked(keys[0], &revoked)) {
ERR_MSG("Error getting key revocation status.");
goto done;
}
if (revoked && !rnp_cfg_getbool(cfg, CFG_FORCE)) {
ERR_MSG("Error: key '%s' is revoked already. Use --force to generate another "
"revocation signature.",
key);
goto done;
}
ret = rnp_key_revoke(keys[0],
0,
rnp_cfg_getstr(cfg, CFG_HASH),
rnp_cfg_getstr(cfg, CFG_REV_TYPE),
rnp_cfg_getstr(cfg, CFG_REV_REASON));
if (ret) {
ERR_MSG("Failed to revoke a key: error %d", (int) ret);
goto done;
}
res = cli_rnp_save_keyrings(rnp);
/* print info about the revoked key */
if (res) {
bool subkey = false;
char *grip = NULL;
if (rnp_key_is_sub(keys[0], &subkey)) {
ERR_MSG("Failed to get key info");
goto done;
}
ret =
subkey ? rnp_key_get_primary_grip(keys[0], &grip) : rnp_key_get_grip(keys[0], &grip);
if (ret || !grip) {
ERR_MSG("Failed to get primary key grip.");
goto done;
}
clear_key_handles(keys);
if (!cli_rnp_keys_matching_string(rnp, keys, grip, CLI_SEARCH_SUBKEYS_AFTER)) {
ERR_MSG("Failed to search for revoked key.");
rnp_buffer_destroy(grip);
goto done;
}
rnp_buffer_destroy(grip);
for (auto handle : keys) {
cli_rnp_print_key_info(rnp->userio_out, rnp->ffi, handle, false, false);
}
}
done:
clear_key_handles(keys);
return res;
}
bool
cli_rnp_add_key(cli_rnp_t *rnp)
{

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

@ -118,6 +118,7 @@ bool cli_rnp_keys_matching_strings(cli_rnp_t * rnp,
int flags);
bool cli_rnp_export_keys(cli_rnp_t *rnp, const char *filter);
bool cli_rnp_export_revocation(cli_rnp_t *rnp, const char *key);
bool cli_rnp_revoke_key(cli_rnp_t *rnp, const char *key);
bool cli_rnp_add_key(cli_rnp_t *rnp);
bool cli_rnp_dump_file(cli_rnp_t *rnp);
bool cli_rnp_armor_file(cli_rnp_t *rnp);

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

@ -50,6 +50,7 @@ extern const char *rnp_keys_progname;
const char *usage = "--help OR\n"
"\t--export-key [options] OR\n"
"\t--export-rev [options] OR\n"
"\t--revoke-key [options] OR\n"
"\t--generate-key [options] OR\n"
"\t--import, --import-keys, --import-sigs [options] OR\n"
"\t--list-keys [options] OR\n"
@ -84,6 +85,7 @@ struct option options[] = {
{"generate-key", optional_argument, NULL, CMD_GENERATE_KEY},
{"export-rev", no_argument, NULL, CMD_EXPORT_REV},
{"export-revocation", no_argument, NULL, CMD_EXPORT_REV},
{"revoke-key", no_argument, NULL, CMD_REVOKE_KEY},
/* debugging commands */
{"help", no_argument, NULL, CMD_HELP},
{"version", no_argument, NULL, CMD_VERSION},
@ -385,6 +387,13 @@ rnp_cmd(cli_rnp_t *rnp, optdefs_t cmd, const char *f)
}
return cli_rnp_export_revocation(rnp, f);
}
case CMD_REVOKE_KEY: {
if (!f) {
ERR_MSG("You need to specify key or subkey to revoke.");
return false;
}
return cli_rnp_revoke_key(rnp, f);
}
case CMD_VERSION:
print_praise();
return true;
@ -415,6 +424,7 @@ setoption(rnp_cfg_t *cfg, optdefs_t *cmd, int val, const char *arg)
case CMD_LIST_KEYS:
case CMD_EXPORT_KEY:
case CMD_EXPORT_REV:
case CMD_REVOKE_KEY:
case CMD_IMPORT:
case CMD_IMPORT_KEYS:
case CMD_IMPORT_SIGS:

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

@ -16,6 +16,7 @@ typedef enum {
CMD_IMPORT_SIGS,
CMD_GENERATE_KEY,
CMD_EXPORT_REV,
CMD_REVOKE_KEY,
CMD_VERSION,
CMD_HELP,

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

@ -28,7 +28,7 @@ find_package(JSON-C 0.11 REQUIRED)
# Note that we do this call early because Google Test will also do
# this but with less strict version requirements, which will cause
# problems for us.
find_package(PythonInterp 2.7 EXACT)
find_package(Python3 COMPONENTS Interpreter)
find_package(GnuPG 2.2 COMPONENTS gpg gpgconf)
include(GoogleTest)
@ -91,6 +91,7 @@ add_executable(rnp_tests
utils-list.cpp
utils-rnpcfg.cpp
issues/1030.cpp
issues/1115.cpp
)
target_include_directories(rnp_tests
@ -135,7 +136,7 @@ function(add_cli_test suite)
set(_test_name cli_tests-${suite})
add_test(
NAME ${_test_name}
COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/cli_tests.py" -v -d "${suite}"
COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/cli_tests.py" -v -d "${suite}"
)
set(_env)
list(APPEND _env
@ -152,7 +153,7 @@ function(add_cli_test suite)
endfunction()
# get a list of test suites
execute_process(
COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/cli_tests.py" -ls
COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/cli_tests.py" -ls
RESULT_VARIABLE _ec
OUTPUT_VARIABLE suitelist
OUTPUT_STRIP_TRAILING_WHITESPACE

45
third_party/rnp/src/tests/cli_common.py поставляемый
Просмотреть файл

@ -34,17 +34,14 @@ def raise_err(msg, log = None):
raise CLIError(msg, log)
def size_to_readable(num, suffix = 'B'):
for unit in ['','K','M','G','T','P','E','Z']:
for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']:
if abs(num) < 1024.0:
return "%3.1f%s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f%s%s" % (num, 'Yi', suffix)
def list_upto(lst, count):
res = lst[:]
while len(res) < count:
res = res + lst[:]
return res[:count]
return (list(lst)*(count//len(lst)+1))[:count]
def pswd_pipe(password):
pr, pw = os.pipe()
@ -52,6 +49,7 @@ def pswd_pipe(password):
fw.write(password)
fw.write('\n')
fw.write(password)
os.set_inheritable(pr, True)
if not is_windows():
return pr
@ -63,15 +61,16 @@ def pswd_pipe(password):
def random_text(path, size):
# Generate random text, with 50% probability good-compressible
if random.randint(0, 10) < 5:
st = ''.join(random.choice(string.ascii_letters + string.digits + " \t\n-,.") for _ in range(size))
st = ''.join(random.choice(string.ascii_letters + string.digits + " \t\n-,.")
for _ in range(size))
else:
st = ''.join(random.choice("abcdef0123456789 \t\n-,.") for _ in range(size))
with open(path, 'w+') as f:
f.write(st)
def file_text(path):
with open(path, 'r') as f:
return f.read()
with open(path, 'rb') as f:
return f.read().decode().replace('\r\r', '\r')
def find_utility(name, exitifnone = True):
path = distutils.spawn.find_executable(name)
@ -100,17 +99,26 @@ def run_proc_windows(proc, params, stdin=None):
exe = os.path.basename(proc)
# We need to escape empty parameters/ones with spaces with quotes
params = map(lambda st: st if (st and not any(x in st for x in [' ','\r','\t'])) else '"%s"' % st, [exe] + params)
params = tuple(map(lambda st: st if (st and not any(x in st for x in [' ','\r','\t'])) else '"%s"' % st, [exe] + params))
sys.stdout.flush()
stdin_path = os.path.join(WORKDIR, 'stdin.txt')
stdout_path = os.path.join(WORKDIR, 'stdout.txt')
stderr_path = os.path.join(WORKDIR, 'stderr.txt')
pass_path = os.path.join(WORKDIR, 'pass.txt')
passfd = 0
passfo = None
try:
idx = params.index('--pass-fd')
if idx < len(params):
passfd = int(params[idx+1])
passfo = os.fdopen(passfd, 'r', closefd=False)
except (ValueError, OSError): pass
# We may use pipes here (ensuring we use dup to inherit handles), but those have limited buffer
# so we'll need to poll process
if stdin:
with open(stdin_path, "wb+") as stdinf:
stdinf.write(stdin)
stdinf.write(stdin.encode() if isinstance(stdin, str) else stdin)
stdin_fl = os.open(stdin_path, os.O_RDONLY | os.O_BINARY)
stdin_no = sys.stdin.fileno()
stdin_cp = os.dup(stdin_no)
@ -120,6 +128,11 @@ def run_proc_windows(proc, params, stdin=None):
stderr_fl = os.open(stderr_path, os.O_CREAT | os.O_RDWR | os.O_BINARY)
stderr_no = sys.stderr.fileno()
stderr_cp = os.dup(stderr_no)
if passfo:
with open(pass_path, "w+") as passf:
passf.write(passfo.read())
pass_fl = os.open(pass_path, os.O_RDONLY | os.O_BINARY)
pass_cp = os.dup(passfd)
try:
os.dup2(stdout_fl, stdout_no)
@ -129,6 +142,9 @@ def run_proc_windows(proc, params, stdin=None):
if stdin:
os.dup2(stdin_fl, stdin_no)
os.close(stdin_fl)
if passfo:
os.dup2(pass_fl, passfd)
os.close(pass_fl)
retcode = os.spawnv(os.P_WAIT, proc, params)
finally:
os.dup2(stdout_cp, stdout_no)
@ -138,12 +154,18 @@ def run_proc_windows(proc, params, stdin=None):
if stdin:
os.dup2(stdin_cp, stdin_no)
os.close(stdin_cp)
if passfo:
os.dup2(pass_cp, passfd)
os.close(pass_cp)
passfo.close()
out = file_text(stdout_path).replace('\r\n', '\n')
err = file_text(stderr_path).replace('\r\n', '\n')
os.unlink(stdout_path)
os.unlink(stderr_path)
if stdin:
os.unlink(stdin_path)
if passfo:
os.unlink(pass_path)
logging.debug(err.strip())
logging.debug(out.strip())
return (retcode, out, err)
@ -154,7 +176,8 @@ def run_proc(proc, params, stdin=None):
return run_proc_windows(proc, params, stdin)
logging.debug((proc + ' ' + ' '.join(params)).strip())
process = Popen([proc] + params, stdout=PIPE, stderr=PIPE, stdin=PIPE if stdin else None)
process = Popen([proc] + params, stdout=PIPE, stderr=PIPE,
stdin=PIPE if stdin else None, close_fds=False, universal_newlines=True)
output, errout = process.communicate(stdin)
retcode = process.poll()
logging.debug(errout.strip())

78
third_party/rnp/src/tests/cli_perf.py поставляемый
Просмотреть файл

@ -55,31 +55,34 @@ def setup(workdir):
# Creating working directory and populating it with test files
RNPDIR = path.join(WORKDIR, '.rnp')
GPGDIR = path.join(WORKDIR, '.gpg')
os.mkdir(RNPDIR, 0700)
os.mkdir(GPGDIR, 0700)
os.mkdir(RNPDIR, 0o700)
os.mkdir(GPGDIR, 0o700)
# Generating key
pipe = pswd_pipe(PASSWORD)
params = ['--homedir', RNPDIR, '--pass-fd', str(pipe), '--userid', 'performance@rnp', '--generate-key']
params = ['--homedir', RNPDIR, '--pass-fd', str(pipe), '--userid', 'performance@rnp',
'--generate-key']
# Run key generation
ret, out, err = run_proc(RNPK, params)
os.close(pipe)
# Importing keys to GnuPG so it can build trustdb and so on
ret, out, err = run_proc(GPG, ['--batch', '--passphrase', '', '--homedir', GPGDIR, '--import', path.join(RNPDIR, 'pubring.gpg'), path.join(RNPDIR, 'secring.gpg')])
ret, out, err = run_proc(GPG, ['--batch', '--passphrase', '', '--homedir', GPGDIR,
'--import', path.join(RNPDIR, 'pubring.gpg'),
path.join(RNPDIR, 'secring.gpg')])
# Generating small file for tests
SMALLSIZE = 3312;
st = 'lorem ipsum dol ' * (SMALLSIZE/16)
SMALLSIZE = 3312
st = 'lorem ipsum dol ' * (SMALLSIZE//16+1)
with open(path.join(WORKDIR, SMALLFILE), 'w+') as small_file:
small_file.write(st)
# Generating large file for tests
print 'Generating large file of size {}'.format(size_to_readable(LARGESIZE))
print('Generating large file of size {}'.format(size_to_readable(LARGESIZE)))
st = '0123456789ABCDEF' * (1024/16)
st = '0123456789ABCDEF' * (1024//16)
with open(path.join(WORKDIR, LARGEFILE), 'w') as fd:
for i in range(0, LARGESIZE / 1024 - 1):
for i in range(0, LARGESIZE // 1024):
fd.write(st)
def run_iterated(iterations, func, src, dst, *args):
@ -96,7 +99,8 @@ def run_iterated(iterations, func, src, dst, *args):
return res
def rnp_symencrypt_file(src, dst, cipher, zlevel = 6, zalgo = 'zip', armor = False):
params = ['--homedir', RNPDIR, '--password', PASSWORD, '--cipher', cipher, '-z', str(zlevel), '--' + zalgo, '-c', src, '--output', dst]
params = ['--homedir', RNPDIR, '--password', PASSWORD, '--cipher', cipher,
'-z', str(zlevel), '--' + zalgo, '-c', src, '--output', dst]
if armor:
params += ['--armor']
ret = run_proc_fast(RNP, params)
@ -104,12 +108,15 @@ def rnp_symencrypt_file(src, dst, cipher, zlevel = 6, zalgo = 'zip', armor = Fal
raise_err('rnp symmetric encryption failed')
def rnp_decrypt_file(src, dst):
ret = run_proc_fast(RNP, ['--homedir', RNPDIR, '--password', PASSWORD, '--decrypt', src, '--output', dst])
ret = run_proc_fast(RNP, ['--homedir', RNPDIR, '--password', PASSWORD, '--decrypt', src,
'--output', dst])
if ret != 0:
raise_err('rnp decryption failed')
def gpg_symencrypt_file(src, dst, cipher = 'AES', zlevel = 6, zalgo = 1, armor = False):
params = ['--homedir', GPGDIR, '-c', '-z', str(zlevel), '--s2k-count', '524288', '--compress-algo', str(zalgo), '--batch', '--passphrase', PASSWORD, '--cipher-algo', cipher, '--output', dst, src]
params = ['--homedir', GPGDIR, '-c', '-z', str(zlevel), '--s2k-count', '524288',
'--compress-algo', str(zalgo), '--batch', '--passphrase', PASSWORD,
'--cipher-algo', cipher, '--output', dst, src]
if armor:
params.insert(2, '--armor')
ret = run_proc_fast(GPG, params)
@ -117,7 +124,9 @@ def gpg_symencrypt_file(src, dst, cipher = 'AES', zlevel = 6, zalgo = 1, armor =
raise_err('gpg symmetric encryption failed for cipher ' + cipher)
def gpg_decrypt_file(src, dst, keypass):
ret = run_proc_fast(GPG, ['--homedir', GPGDIR, '--pinentry-mode=loopback', '--batch', '--yes', '--passphrase', keypass, '--trust-model', 'always', '-o', dst, '-d', src])
ret = run_proc_fast(GPG, ['--homedir', GPGDIR, '--pinentry-mode=loopback', '--batch',
'--yes', '--passphrase', keypass, '--trust-model', 'always',
'-o', dst, '-d', src])
if ret != 0:
raise_err('gpg decryption failed')
@ -132,10 +141,12 @@ def print_test_results(fsize, rnptime, gpgtime, operation):
if rnpruns >= gpgruns:
percents = (rnpruns - gpgruns) / gpgruns * 100
logging.info('{:<30}: RNP is {:>3.0f}% FASTER then GnuPG ({})'.format(operation, percents, runstr))
logging.info('{:<30}: RNP is {:>3.0f}% FASTER then GnuPG ({})'.format(
operation, percents, runstr))
else:
percents = (gpgruns - rnpruns) / gpgruns * 100
logging.info('{:<30}: RNP is {:>3.0f}% SLOWER then GnuPG ({})'.format(operation, percents, runstr))
logging.info('{:<30}: RNP is {:>3.0f}% SLOWER then GnuPG ({})'.format(
operation, percents, runstr))
else:
rnpspeed = fsize / 1024.0 / 1024.0 / rnptime
gpgspeed = fsize / 1024.0 / 1024.0 / gpgtime
@ -143,16 +154,20 @@ def print_test_results(fsize, rnptime, gpgtime, operation):
if rnpspeed >= gpgspeed:
percents = (rnpspeed - gpgspeed) / gpgspeed * 100
logging.info('{:<30}: RNP is {:>3.0f}% FASTER then GnuPG ({})'.format(operation, percents, spdstr))
logging.info('{:<30}: RNP is {:>3.0f}% FASTER then GnuPG ({})'.format(
operation, percents, spdstr))
else:
percents = (gpgspeed - rnpspeed) / gpgspeed * 100
logging.info('{:<30}: RNP is {:>3.0f}% SLOWER then GnuPG ({})'.format(operation, percents, spdstr))
logging.info('{:<30}: RNP is {:>3.0f}% SLOWER then GnuPG ({})'.format(
operation, percents, spdstr))
def get_file_params(filetype):
if filetype == 'small':
infile, outfile, iterations, fsize = (SMALLFILE, SMALLFILE + '.gpg', SMALL_ITERATIONS, SMALLSIZE)
infile, outfile, iterations, fsize = (SMALLFILE, SMALLFILE + '.gpg',
SMALL_ITERATIONS, SMALLSIZE)
else:
infile, outfile, iterations, fsize = (LARGEFILE, LARGEFILE + '.gpg', LARGE_ITERATIONS, LARGESIZE)
infile, outfile, iterations, fsize = (LARGEFILE, LARGEFILE + '.gpg',
LARGE_ITERATIONS, LARGESIZE)
infile = path.join(WORKDIR, infile)
rnpout = path.join(WORKDIR, outfile + '.rnp')
@ -172,8 +187,10 @@ class Benchmark(object):
'''
infile, rnpout, gpgout, iterations, fsize = get_file_params('small')
for armor in [False, True]:
tmrnp = run_iterated(iterations, rnp_symencrypt_file, infile, rnpout, 'AES128', 0, 'zip', armor)
tmgpg = run_iterated(iterations, gpg_symencrypt_file, infile, gpgout, 'AES128', 0, 1, armor)
tmrnp = run_iterated(iterations, rnp_symencrypt_file, infile, rnpout,
'AES128', 0, 'zip', armor)
tmgpg = run_iterated(iterations, gpg_symencrypt_file, infile, gpgout,
'AES128', 0, 1, armor)
testname = 'ENCRYPT-SMALL-{}'.format('ARMOR' if armor else 'BINARY')
print_test_results(fsize, tmrnp, tmgpg, testname)
@ -183,8 +200,10 @@ class Benchmark(object):
'''
infile, rnpout, gpgout, iterations, fsize = get_file_params('large')
for cipher in ['AES128', 'AES192', 'AES256', 'TWOFISH', 'BLOWFISH', 'CAST5', 'CAMELLIA128', 'CAMELLIA192', 'CAMELLIA256']:
tmrnp = run_iterated(iterations, rnp_symencrypt_file, infile, rnpout, cipher, 0, 'zip', False)
tmgpg = run_iterated(iterations, gpg_symencrypt_file, infile, gpgout, cipher, 0, 1, False)
tmrnp = run_iterated(iterations, rnp_symencrypt_file, infile, rnpout,
cipher, 0, 'zip', False)
tmgpg = run_iterated(iterations, gpg_symencrypt_file, infile, gpgout,
cipher, 0, 1, False)
testname = 'ENCRYPT-{}-BINARY'.format(cipher)
print_test_results(fsize, tmrnp, tmgpg, testname)
@ -193,7 +212,8 @@ class Benchmark(object):
Large file armored encryption
'''
infile, rnpout, gpgout, iterations, fsize = get_file_params('large')
tmrnp = run_iterated(iterations, rnp_symencrypt_file, infile, rnpout, 'AES128', 0, 'zip', True)
tmrnp = run_iterated(iterations, rnp_symencrypt_file, infile, rnpout,
'AES128', 0, 'zip', True)
tmgpg = run_iterated(iterations, gpg_symencrypt_file, infile, gpgout, 'AES128', 0, 1, True)
print_test_results(fsize, tmrnp, tmgpg, 'ENCRYPT-LARGE-ARMOR')
@ -217,7 +237,8 @@ class Benchmark(object):
'''
infile, rnpout, gpgout, iterations, fsize = get_file_params('large')
inenc = infile + '.enc'
for cipher in ['AES128', 'AES192', 'AES256', 'TWOFISH', 'BLOWFISH', 'CAST5', 'CAMELLIA128', 'CAMELLIA192', 'CAMELLIA256']:
for cipher in ['AES128', 'AES192', 'AES256', 'TWOFISH', 'BLOWFISH', 'CAST5',
'CAMELLIA128', 'CAMELLIA192', 'CAMELLIA256']:
gpg_symencrypt_file(infile, inenc, cipher, 0, 1, False)
tmrnp = run_iterated(iterations, rnp_decrypt_file, inenc, rnpout)
tmgpg = run_iterated(iterations, gpg_decrypt_file, inenc, gpgout, PASSWORD)
@ -266,11 +287,14 @@ if __name__ == '__main__':
help="Name of the comma-separated benchmarks to run", metavar="benchmarks")
parser.add_argument("-w", "--workdir", dest="workdir",
help="Working directory to use", metavar="workdir")
parser.add_argument("-l", "--list", help="Print list of available benchmarks and exit", action="store_true")
parser.add_argument("-l", "--list", help="Print list of available benchmarks and exit",
action="store_true")
args = parser.parse_args()
# get list of benchamrks to run
bench_methods = [ x[0] for x in inspect.getmembers(Benchmark,predicate=inspect.ismethod) if not x[0].startswith("_") ]
bench_methods = [ x[0] for x in inspect.getmembers(Benchmark,
predicate=lambda x: inspect.ismethod(x) or inspect.isfunction(x))]
print(bench_methods)
if args.list:
for name in bench_methods:

332
third_party/rnp/src/tests/cli_tests.py поставляемый
Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
import itertools
import logging
@ -124,9 +124,11 @@ r'new key revocations: 1.*$'
RNP_TO_GPG_ZALGS = { 'zip' : '1', 'zlib' : '2', 'bzip2' : '3' }
# These are mostly identical
RNP_TO_GPG_CIPHERS = {'AES' : 'aes128', 'AES192' : 'aes192', 'AES256' : 'aes256', 'TWOFISH' : 'twofish',
'CAMELLIA128' : 'camellia128', 'CAMELLIA192' : 'camellia192', 'CAMELLIA256' : 'camellia256',
'IDEA' : 'idea', '3DES' : '3des', 'CAST5' : 'cast5', 'BLOWFISH' : 'blowfish'}
RNP_TO_GPG_CIPHERS = {'AES' : 'aes128', 'AES192' : 'aes192', 'AES256' : 'aes256',
'TWOFISH' : 'twofish', 'CAMELLIA128' : 'camellia128',
'CAMELLIA192' : 'camellia192', 'CAMELLIA256' : 'camellia256',
'IDEA' : 'idea', '3DES' : '3des', 'CAST5' : 'cast5',
'BLOWFISH' : 'blowfish'}
def check_packets(fname, regexp):
ret, output, err = run_proc(GPG, ['--list-packets', path_for_gpg(fname)])
@ -143,7 +145,7 @@ def check_packets(fname, regexp):
def clear_keyrings():
shutil.rmtree(RNPDIR, ignore_errors=True)
os.mkdir(RNPDIR, 0700)
os.mkdir(RNPDIR, 0o700)
run_proc(GPGCONF, ['--homedir', GPGHOME, '--kill', 'gpg-agent'])
while os.path.isdir(GPGDIR):
@ -151,7 +153,7 @@ def clear_keyrings():
shutil.rmtree(GPGDIR)
except:
time.sleep(0.1)
os.mkdir(GPGDIR, 0700)
os.mkdir(GPGDIR, 0o700)
def compare_files(src, dst, message):
if file_text(src) != file_text(dst):
@ -201,8 +203,8 @@ def clear_workfiles():
def rnp_genkey_rsa(userid, bits=2048, pswd=PASSWORD):
pipe = pswd_pipe(pswd)
ret, _, err = run_proc(RNPK, ['--numbits', str(bits), '--homedir',
RNPDIR, '--pass-fd', str(pipe), '--userid', userid, '--generate-key'])
ret, _, err = run_proc(RNPK, ['--numbits', str(bits), '--homedir', RNPDIR, '--pass-fd',
str(pipe), '--userid', userid, '--generate-key'])
os.close(pipe)
if ret != 0:
raise_err('rsa key generation failed', err)
@ -221,7 +223,8 @@ def rnp_params_insert_aead(params, pos, aead):
if len(aead) > 1 and aead[1] != None:
params[pos + 1:pos + 1] = ['--aead-chunk-bits=' + str(aead[1])]
def rnp_encrypt_file_ex(src, dst, recipients=None, passwords=None, aead=None, cipher=None, z=None, armor=False):
def rnp_encrypt_file_ex(src, dst, recipients=None, passwords=None, aead=None, cipher=None,
z=None, armor=False):
params = ['--homedir', RNPDIR, src, '--output', dst]
# Recipients. None disables PK encryption, [] to use default key. Otheriwse list of ids.
if recipients != None:
@ -247,7 +250,8 @@ def rnp_encrypt_file_ex(src, dst, recipients=None, passwords=None, aead=None, ci
if ret != 0:
raise_err('rnp encryption failed', err)
def rnp_encrypt_and_sign_file(src, dst, recipients, encrpswd, signers, signpswd, aead=None, cipher=None, z=None, armor=False):
def rnp_encrypt_and_sign_file(src, dst, recipients, encrpswd, signers, signpswd,
aead=None, cipher=None, z=None, armor=False):
params = ['--homedir', RNPDIR, '--sign', '--encrypt', src, '--output', dst]
pipe = pswd_pipe('\n'.join(encrpswd + signpswd))
params[2:2] = ['--pass-fd', str(pipe)]
@ -374,8 +378,9 @@ def gpg_import_secring(kpath=None, password = PASSWORD):
def gpg_export_secret_key(userid, password, keyfile):
ret, _, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--pinentry-mode=loopback', '--yes',
'--passphrase', password, '--output', path_for_gpg(keyfile), '--export-secret-key', userid])
ret, _, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--pinentry-mode=loopback',
'--yes', '--passphrase', password, '--output',
path_for_gpg(keyfile), '--export-secret-key', userid])
if ret != 0:
raise_err('gpg secret key export failed', err)
@ -390,7 +395,8 @@ def gpg_params_insert_z(params, pos, z):
def gpg_encrypt_file(src, dst, cipher=None, z=None, armor=False):
src = path_for_gpg(src)
dst = path_for_gpg(dst)
params = ['--homedir', GPGHOME, '-e', '-r', KEY_ENCRYPT, '--batch', '--trust-model', 'always', '--output', dst, src]
params = ['--homedir', GPGHOME, '-e', '-r', KEY_ENCRYPT, '--batch',
'--trust-model', 'always', '--output', dst, src]
if z: gpg_params_insert_z(params, 3, z)
if cipher: params[3:3] = ['--cipher-algo', RNP_TO_GPG_CIPHERS[cipher]]
if armor: params[2:2] = ['--armor']
@ -403,7 +409,8 @@ def gpg_encrypt_file(src, dst, cipher=None, z=None, armor=False):
def gpg_symencrypt_file(src, dst, cipher=None, z=None, armor=False, aead=None):
src = path_for_gpg(src)
dst = path_for_gpg(dst)
params = ['--homedir', GPGHOME, '-c', '--s2k-count', '65536', '--batch', '--passphrase', PASSWORD, '--output', dst, src]
params = ['--homedir', GPGHOME, '-c', '--s2k-count', '65536', '--batch',
'--passphrase', PASSWORD, '--output', dst, src]
if z: gpg_params_insert_z(params, 3, z)
if cipher: params[3:3] = ['--cipher-algo', RNP_TO_GPG_CIPHERS[cipher]]
if armor: params[2:2] = ['--armor']
@ -423,7 +430,8 @@ def gpg_decrypt_file(src, dst, keypass):
src = path_for_gpg(src)
dst = path_for_gpg(dst)
ret, out, err = run_proc(GPG, ['--homedir', GPGHOME, '--pinentry-mode=loopback', '--batch',
'--yes', '--passphrase', keypass, '--trust-model', 'always', '-o', dst, '-d', src])
'--yes', '--passphrase', keypass, '--trust-model',
'always', '-o', dst, '-d', src])
if ret != 0:
raise_err('gpg decryption failed', err)
@ -446,8 +454,8 @@ def gpg_verify_file(src, dst, signer=None):
def gpg_verify_detached(src, sig, signer=None):
src = path_for_gpg(src)
sig = path_for_gpg(sig)
ret, _, err = run_proc(GPG, ['--homedir', GPGHOME, '--batch',
'--yes', '--trust-model', 'always', '--verify', sig, src])
ret, _, err = run_proc(GPG, ['--homedir', GPGHOME, '--batch', '--yes', '--trust-model',
'always', '--verify', sig, src])
if ret != 0:
raise_err('gpg detached verification failed', err)
# Check GPG output
@ -476,7 +484,8 @@ def gpg_sign_file(src, dst, signer, z=None, armor=False):
src = path_for_gpg(src)
dst = path_for_gpg(dst)
params = ['--homedir', GPGHOME, '--pinentry-mode=loopback', '--batch', '--yes',
'--passphrase', PASSWORD, '--trust-model', 'always', '-u', signer, '-o', dst, '-s', src]
'--passphrase', PASSWORD, '--trust-model', 'always', '-u', signer, '-o',
dst, '-s', src]
if z: gpg_params_insert_z(params, 3, z)
if armor: params.insert(2, '--armor')
ret, _, err = run_proc(GPG, params)
@ -487,7 +496,8 @@ def gpg_sign_file(src, dst, signer, z=None, armor=False):
def gpg_sign_detached(src, signer, armor=False):
src = path_for_gpg(src)
params = ['--homedir', GPGHOME, '--pinentry-mode=loopback', '--batch', '--yes',
'--passphrase', PASSWORD, '--trust-model', 'always', '-u', signer, '--detach-sign', src]
'--passphrase', PASSWORD, '--trust-model', 'always', '-u', signer,
'--detach-sign', src]
if armor: params.insert(2, '--armor')
ret, _, err = run_proc(GPG, params)
if ret != 0:
@ -726,13 +736,13 @@ def setup(loglvl):
RNPDIR = path.join(WORKDIR, '.rnp')
RNP = os.getenv('RNP_TESTS_RNP_PATH') or 'rnp'
RNPK = os.getenv('RNP_TESTS_RNPKEYS_PATH') or 'rnpkeys'
os.mkdir(RNPDIR, 0700)
os.mkdir(RNPDIR, 0o700)
GPGDIR = path.join(WORKDIR, '.gpg')
GPGHOME = path_for_gpg(GPGDIR) if is_windows() else GPGDIR
GPG = os.getenv('RNP_TESTS_GPG_PATH') or find_utility('gpg')
GPGCONF = os.getenv('RNP_TESTS_GPGCONF_PATH') or find_utility('gpgconf')
os.mkdir(GPGDIR, 0700)
os.mkdir(GPGDIR, 0o700)
def data_path(subpath):
''' Constructs path to the tests data file/dir'''
@ -740,7 +750,8 @@ def data_path(subpath):
def key_path(file_base_name, secret):
''' Constructs path to the .gpg file'''
path=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/cli_EncryptSign', file_base_name)
path=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data/cli_EncryptSign',
file_base_name)
return ''.join([path, '-sec' if secret else '', '.gpg'])
class TestIdMixin(object):
@ -806,8 +817,8 @@ class Keystore(unittest.TestCase):
userid = str(bits) + '@rnptest'
# Open pipe for password
pipe = pswd_pipe(PASSWORD)
params = params + ['--homedir', RNPDIR, '--pass-fd',
str(pipe), '--userid', userid, '--generate-key']
params = params + ['--homedir', RNPDIR, '--pass-fd', str(pipe),
'--userid', userid, '--generate-key']
# Run key generation
ret, out, err = run_proc(RNPK, params)
os.close(pipe)
@ -836,8 +847,9 @@ class Keystore(unittest.TestCase):
if not match.group(1) == str(bits):
raise_err('wrong key bits in list')
# Import key to the gnupg
ret, out, err = run_proc(GPG, ['--batch', '--passphrase', PASSWORD, '--homedir', GPGHOME,
'--import', path_for_gpg(path.join(RNPDIR, 'pubring.gpg')),
ret, out, err = run_proc(GPG, ['--batch', '--passphrase', PASSWORD, '--homedir',
GPGHOME, '--import',
path_for_gpg(path.join(RNPDIR, 'pubring.gpg')),
path_for_gpg(path.join(RNPDIR, 'secring.gpg'))])
if ret != 0:
raise_err('gpg key import failed', err)
@ -858,7 +870,8 @@ class Keystore(unittest.TestCase):
pipe = pswd_pipe(PASSWORD)
userid = str(i) + '@rnp-multiple'
ret, out, err = run_proc(RNPK, ['--numbits', '2048', '--homedir', RNPDIR,
'--pass-fd', str(pipe), '--userid', userid, '--generate-key'])
'--pass-fd', str(pipe), '--userid', userid,
'--generate-key'])
os.close(pipe)
if ret != 0:
raise_err('key generation failed', err)
@ -889,8 +902,8 @@ class Keystore(unittest.TestCase):
Generate key with GnuPG and import it to rnp
'''
# Generate key in GnuPG
ret, out, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME,
'--passphrase', '', '--quick-generate-key', 'rsakey@gpg', 'rsa'])
ret, out, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--passphrase',
'', '--quick-generate-key', 'rsakey@gpg', 'rsa'])
if ret != 0:
raise_err('gpg key generation failed, error ' + str(ret) , err)
# Getting fingerprint of the generated key
@ -936,7 +949,8 @@ class Keystore(unittest.TestCase):
# Open pipe for password
pipe = pswd_pipe(PASSWORD)
# Run key generation
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--pass-fd', str(pipe), '--userid', 'rsakey@rnp', '--generate-key'])
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--pass-fd', str(pipe),
'--userid', 'rsakey@rnp', '--generate-key'])
os.close(pipe)
if ret != 0: raise_err('key generation failed', err)
# Export key
@ -946,7 +960,8 @@ class Keystore(unittest.TestCase):
with open(pubpath, 'w+') as f:
f.write(out)
# Import key with GPG
ret, out, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--import', path_for_gpg(pubpath)])
ret, out, err = run_proc(GPG, ['--batch', '--homedir', GPGHOME, '--import',
path_for_gpg(pubpath)])
if ret != 0: raise_err('gpg : public key import failed', err)
def test_generate_to_kbx(self):
@ -957,8 +972,9 @@ class Keystore(unittest.TestCase):
pipe = pswd_pipe(PASSWORD)
kbx_userid_tracker = 'kbx_userid_tracker@rnp'
# Run key generation
ret, out, err = run_proc(RNPK, ['--gen-key', '--keystore-format', 'GPG21', '--userid', kbx_userid_tracker,
'--homedir', RNPDIR, '--pass-fd', str(pipe)])
ret, out, err = run_proc(RNPK, ['--gen-key', '--keystore-format', 'GPG21',
'--userid', kbx_userid_tracker, '--homedir',
RNPDIR, '--pass-fd', str(pipe)])
os.close(pipe)
if ret != 0: raise_err('key generation failed', err)
# Read KBX with GPG
@ -975,7 +991,8 @@ class Keystore(unittest.TestCase):
# Open pipe for password
pipe = pswd_pipe(PASSWORD)
# Run key generation
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--pass-fd', str(pipe), '--userid', 'enc@rnp', '--generate-key'])
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--pass-fd', str(pipe),
'--userid', 'enc@rnp', '--generate-key'])
os.close(pipe)
if ret != 0:
raise_err('key generation failed', err)
@ -1200,6 +1217,90 @@ class Keystore(unittest.TestCase):
raise_err('userids from rnpkeys and gpg don\'t match')
clear_keyrings()
def test_key_revoke(self):
clear_keyrings()
# Import Alice's public key and be unable to revoke
ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-pub.asc')])
if ret != 0:
raise_err('Alice key import failed')
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke-key', 'alice'])
if (ret == 0) or (len(out) > 0) or not re.match(r'(?s)^.*Revoker secret key not found.*Failed to revoke a key.*', err):
raise_err('Wrong revocation output')
# Import Alice's secret key and subkey
ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/alice-sub-sec.pgp')])
if ret != 0:
raise_err('Alice secret key import failed')
# Attempt to revoke without specifying a key
pipe = pswd_pipe(PASSWORD)
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', '--pass-fd', str(pipe)])
os.close(pipe)
if (ret == 0) or (len(out) > 0) or not re.match(r'(?s)^.*You need to specify key or subkey to revoke.*', err):
raise_err('Wrong revocation output', err)
# Attempt to revoke unknown key
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', 'basil'])
if (ret == 0) or (len(out) > 0) or not re.match(r'(?s)^.*Key matching \'basil\' not found.*', err):
raise_err('Wrong revocation output', err)
# Attempt to revoke with too broad search
ret, _, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--import', data_path('test_key_validity/basil-sec.asc')])
if ret != 0:
raise_err('Basil secret key import failed')
pipe = pswd_pipe(PASSWORD)
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', 'rnp', '--pass-fd', str(pipe)])
os.close(pipe)
if not re.match(r'(?s)^.*Ambiguous input: too many keys found for \'rnp\'.*', err):
raise_err('Wrong revocation export output', err)
# Revoke a primary key
pipe = pswd_pipe(PASSWORD)
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', '0451409669FFDE3C', '--pass-fd', str(pipe)])
os.close(pipe)
if (ret != 0):
raise_err('Failed to revoke alice key')
ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys'])
if (ret != 0) or not re.match(r'(?s)^.*pub.*0451409669ffde3c.*\[REVOKED\].*73edcc9119afc8e2dbbdcde50451409669ffde3c.*', out):
raise_err('Wrong revoked key listing', out)
# Try again without the '--force' parameter
pipe = pswd_pipe(PASSWORD)
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', '0451409669FFDE3C', '--pass-fd', str(pipe)])
os.close(pipe)
if (ret == 0):
raise_err('Failed to fail to revoke alice key')
if (len(out) > 0) or not re.match(r'(?s)^.*Error: key \'0451409669FFDE3C\' is revoked already. Use --force to generate another revocation signature.*', err):
raise_err('Wrong revocation output', err)
# Try again with --force parameter
pipe = pswd_pipe(PASSWORD)
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', '0451409669FFDE3C', '--pass-fd', str(pipe), "--force", "--rev-type", "3", "--rev-reason", "Custom"])
os.close(pipe)
if (ret != 0):
raise_err('Failed to revoke alice key')
ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys'])
if (ret != 0) or not re.match(r'(?s)^.*pub.*0451409669ffde3c.*\[REVOKED\].*73edcc9119afc8e2dbbdcde50451409669ffde3c.*', out):
raise_err('Wrong revoked key listing', out)
# Revoke a subkey
pipe = pswd_pipe(PASSWORD)
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', 'DD23CEB7FEBEFF17', '--pass-fd', str(pipe)])
os.close(pipe)
if (ret != 0):
raise_err('Failed to revoke alice subkey')
ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys'])
if (ret != 0) or not re.match(r'(?s)^.*sub.*dd23ceb7febeff17.*\[REVOKED\].*a4bbb77370217bca2307ad0ddd23ceb7febeff17.*', out):
raise_err('Wrong revoked subkey listing', out)
# Try again without the '--force' parameter
pipe = pswd_pipe(PASSWORD)
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', 'DD23CEB7FEBEFF17', '--pass-fd', str(pipe)])
os.close(pipe)
if (ret == 0):
raise_err('Failed to fail to revoke alice subkey')
if (len(out) > 0) or not re.match(r'(?s)^.*Error: key \'DD23CEB7FEBEFF17\' is revoked already. Use --force to generate another revocation signature.*', err):
raise_err('Wrong revocation output', err)
# Try again with --force parameter
pipe = pswd_pipe(PASSWORD)
ret, out, err = run_proc(RNPK, ['--homedir', RNPDIR, '--revoke', 'DD23CEB7FEBEFF17', '--pass-fd', str(pipe), "--force", "--rev-type", "2", "--rev-reason", "Other"])
os.close(pipe)
if (ret != 0):
raise_err('Failed to revoke alice subkey')
ret, out, _ = run_proc(RNPK, ['--homedir', RNPDIR, '--list-keys'])
if (ret != 0) or not re.match(r'(?s)^.*sub.*dd23ceb7febeff17.*\[REVOKED\].*a4bbb77370217bca2307ad0ddd23ceb7febeff17.*', out):
raise_err('Wrong revoked subkey listing', out)
class Misc(unittest.TestCase):
@ -1222,7 +1323,9 @@ class Misc(unittest.TestCase):
# Generate random file of required size
random_text(src, 64000)
# Encrypt cleartext file with GPG
params = ['--homedir', GPGHOME, '-c', '-z', '0', '--disable-mdc', '--s2k-count', '65536', '--batch', '--passphrase', PASSWORD, '--output', path_for_gpg(dst), path_for_gpg(src)]
params = ['--homedir', GPGHOME, '-c', '-z', '0', '--disable-mdc', '--s2k-count',
'65536', '--batch', '--passphrase', PASSWORD, '--output',
path_for_gpg(dst), path_for_gpg(src)]
ret, _, err = run_proc(GPG, params)
if ret != 0:
raise_err('gpg symmetric encryption failed', err)
@ -1234,14 +1337,15 @@ class Misc(unittest.TestCase):
src, dst, dec = reg_workfiles('cleartext', '.txt', '.gpg', '.rnp')
random_text(src, 64000)
ciphers = ['AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128',
'CAMELLIA192', 'CAMELLIA256', 'IDEA', '3DES', 'CAST5', 'BLOWFISH']
ciphers = ['AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128', 'CAMELLIA192',
'CAMELLIA256', 'IDEA', '3DES', 'CAST5', 'BLOWFISH']
hashes = ['SHA1', 'RIPEMD160', 'SHA256', 'SHA384', 'SHA512', 'SHA224']
s2kmodes = [0, 1, 3]
def rnp_encryption_s2k_gpg(cipher, hash_alg, s2k=None, iterations=None):
params = ['--homedir', GPGHOME, '-c', '--s2k-cipher-algo', cipher, '--s2k-digest-algo',
hash_alg, '--batch', '--passphrase', PASSWORD, '--output', dst, src]
params = ['--homedir', GPGHOME, '-c', '--s2k-cipher-algo', cipher,
'--s2k-digest-algo', hash_alg, '--batch', '--passphrase', PASSWORD,
'--output', dst, src]
if s2k is not None:
params.insert(7, '--s2k-mode')
@ -1263,8 +1367,10 @@ class Misc(unittest.TestCase):
i % len(hashes)], s2kmodes[i % len(s2kmodes)])
def test_armor(self):
src_beg, dst_beg, dst_mid, dst_fin = reg_workfiles('beg','.src','.dst', '.mid.dst', '.fin.dst')
armor_types = [('msg', 'MESSAGE'), ('pubkey', 'PUBLIC KEY BLOCK'), ('seckey', 'PRIVATE KEY BLOCK'), ('sign', 'SIGNATURE')]
src_beg, dst_beg, dst_mid, dst_fin = reg_workfiles('beg', '.src', '.dst',
'.mid.dst', '.fin.dst')
armor_types = [('msg', 'MESSAGE'), ('pubkey', 'PUBLIC KEY BLOCK'),
('seckey', 'PRIVATE KEY BLOCK'), ('sign', 'SIGNATURE')]
for data_type, header in armor_types:
random_text(src_beg, 1000)
@ -1293,7 +1399,8 @@ class Misc(unittest.TestCase):
compare_file(path + 'keyring_1_list_sigs', out, 'keyring 1 sig listing failed')
_, out, _ = run_proc(RNPK, ['--home', data_path('keyrings/1'), '--list-keys', '--secret'])
compare_file(path + 'keyring_1_list_keys_sec', out, 'keyring 1 sec key listing failed')
_, out, _ = run_proc(RNPK, ['--home', data_path('keyrings/1'), '--list-keys', '--secret', '--with-sigs'])
_, out, _ = run_proc(RNPK, ['--home', data_path('keyrings/1'), '--list-keys',
'--secret', '--with-sigs'])
compare_file(path + 'keyring_1_list_sigs_sec', out, 'keyring 1 sec sig listing failed')
_, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/2'), '--list-keys'])
@ -1311,21 +1418,30 @@ class Misc(unittest.TestCase):
_, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/5'), '-l', '--with-sigs'])
compare_file(path + 'keyring_5_list_sigs', out, 'keyring 5 sig listing failed')
_, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'), '--list-keys'])
_, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'),
'--list-keys'])
compare_file(path + 'test_stream_key_load_keys', out, 'g10 keyring key listing failed')
_, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'), '-l', '--with-sigs'])
_, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'),
'-l', '--with-sigs'])
compare_file(path + 'test_stream_key_load_sigs', out, 'g10 keyring sig listing failed')
# Below are disabled until we have some kind of sorting which doesn't depend on readdir order
#_, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'), '-l', '--secret'])
#compare_file(path + 'test_stream_key_load_keys_sec', out, 'g10 sec keyring key listing failed')
#_, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'), '-l', '--secret', '--with-sigs'])
#compare_file(path + 'test_stream_key_load_sigs_sec', out, 'g10 sec keyring sig listing failed')
# Below are disabled until we have some kind of sorting which doesn't depend on
# readdir order
#_, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'),
# '-l', '--secret'])
#compare_file(path + 'test_stream_key_load_keys_sec', out,
# 'g10 sec keyring key listing failed')
#_, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'),
# '-l', '--secret', '--with-sigs'])
#compare_file(path + 'test_stream_key_load_sigs_sec', out,
# 'g10 sec keyring sig listing failed')
_, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '-l', '2fcadf05ffa501bb'])
compare_file(path + 'getkey_2fcadf05ffa501bb', out, 'list key 2fcadf05ffa501bb failed')
_, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '-l', '--with-sigs', '2fcadf05ffa501bb'])
_, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '-l',
'--with-sigs', '2fcadf05ffa501bb'])
compare_file(path + 'getkey_2fcadf05ffa501bb_sig', out, 'list sig 2fcadf05ffa501bb failed')
_, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '-l', '--secret', '2fcadf05ffa501bb'])
_, out, _ = run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '-l',
'--secret', '2fcadf05ffa501bb'])
compare_file(path + 'getkey_2fcadf05ffa501bb_sec', out, 'list sec 2fcadf05ffa501bb failed')
_, out, err = run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '-l', '00000000'])
@ -1334,10 +1450,13 @@ class Misc(unittest.TestCase):
compare_file(path + 'getkey_zzzzzzzz', out, 'list key zzzzzzzz failed')
def test_rnpkeys_g10_list_order(self):
_, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'), '--list-keys'])
_, out, _ = run_proc(RNPK, ['--homedir', data_path(
'test_stream_key_load/g10'), '--list-keys'])
compare_file(data_path('test_cli_rnpkeys/g10_list_keys'), out, 'g10 key listing failed')
_, out, _ = run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'), '--secret', '--list-keys'])
compare_file(data_path('test_cli_rnpkeys/g10_list_keys_sec'), out, 'g10 secret key listing failed')
_, out, _ = run_proc(RNPK, ['--homedir', data_path(
'test_stream_key_load/g10'), '--secret', '--list-keys'])
compare_file(data_path('test_cli_rnpkeys/g10_list_keys_sec'), out,
'g10 secret key listing failed')
return
def test_rnpkeys_g10_def_key(self):
@ -1352,7 +1471,8 @@ class Misc(unittest.TestCase):
src, dst = reg_workfiles('cleartext', '.txt', '.rnp')
random_text(src, 1000)
# Sign file with rnp using the default g10 key
params = ['--homedir', data_path('test_cli_g10_defkey/g10'), '--password', PASSWORD, '--output', dst, '-s', src]
params = ['--homedir', data_path('test_cli_g10_defkey/g10'),
'--password', PASSWORD, '--output', dst, '-s', src]
ret, _, err = run_proc(RNP, params)
if ret != 0:
raise_err('rnp signing failed', err)
@ -1398,7 +1518,8 @@ class Misc(unittest.TestCase):
mpath = path_for_gpg(data_path('test_partial_length/message.txt.partial-zero-last'))
ret, _, err = run_proc(GPG, ['--homedir', GPGHOME, '--keyring', kpath, '--verify', mpath])
if ret != 0:
raise_err('message in partial packets having 0-size last chunk verification failed', err)
raise_err('message in partial packets having 0-size last chunk ' \
'verification failed', err)
return
def test_partial_length_largest(self):
@ -1416,7 +1537,8 @@ class Misc(unittest.TestCase):
ret, out, err = run_proc(RNP, params)
if ret != 0:
raise_err('packet listing failed', err)
compare_file_ex(data_path('test_list_packets/list_standard.txt'), out, 'standard listing mismatch')
compare_file_ex(data_path('test_list_packets/list_standard.txt'), out,
'standard listing mismatch')
# List packets with mpi values
params = ['--mpi', '--list-packets', data_path('test_list_packets/ecc-p256-pub.asc')]
ret, out, err = run_proc(RNP, params)
@ -1428,7 +1550,8 @@ class Misc(unittest.TestCase):
ret, out, err = run_proc(RNP, params)
if ret != 0:
raise_err('packet listing with grips failed', err)
compare_file_ex(data_path('test_list_packets/list_grips.txt'), out, 'grips listing mismatch')
compare_file_ex(data_path('test_list_packets/list_grips.txt'), out,
'grips listing mismatch')
# List packets with raw packet contents
params = ['--list-packets', data_path('test_list_packets/ecc-p256-pub.asc'), '--raw']
ret, out, err = run_proc(RNP, params)
@ -1436,7 +1559,8 @@ class Misc(unittest.TestCase):
raise_err('packet listing with raw packets failed', err)
compare_file_ex(data_path('test_list_packets/list_raw.txt'), out, 'raw listing mismatch')
# List packets with all options enabled
params = ['--list-packets', data_path('test_list_packets/ecc-p256-pub.asc'), '--grips', '--raw', '--mpi']
params = ['--list-packets', data_path('test_list_packets/ecc-p256-pub.asc'),
'--grips', '--raw', '--mpi']
ret, out, err = run_proc(RNP, params)
if ret != 0:
raise_err('packet listing with all options failed', err)
@ -1449,36 +1573,45 @@ class Misc(unittest.TestCase):
raise_err('json packet listing failed', err)
compare_file_ex(data_path('test_list_packets/list_json.txt'), out, 'json listing mismatch')
# List packets with mpi values, JSON output
params = ['--json', '--mpi', '--list-packets', data_path('test_list_packets/ecc-p256-pub.asc')]
params = ['--json', '--mpi', '--list-packets', data_path(
'test_list_packets/ecc-p256-pub.asc')]
ret, out, err = run_proc(RNP, params)
if ret != 0:
raise_err('json mpi packet listing failed', err)
compare_file_ex(data_path('test_list_packets/list_json_mpi.txt'), out, 'json mpi listing mismatch')
compare_file_ex(data_path('test_list_packets/list_json_mpi.txt'), out,
'json mpi listing mismatch')
# List packets with grip/fingerprint values, JSON output
params = ['--json', '--grips', '--list-packets', data_path('test_list_packets/ecc-p256-pub.asc')]
params = ['--json', '--grips', '--list-packets', data_path(
'test_list_packets/ecc-p256-pub.asc')]
ret, out, err = run_proc(RNP, params)
if ret != 0:
raise_err('json grips packet listing failed', err)
compare_file_ex(data_path('test_list_packets/list_json_grips.txt'), out, 'json grips listing mismatch')
compare_file_ex(data_path('test_list_packets/list_json_grips.txt'), out,
'json grips listing mismatch')
# List packets with raw packet values, JSON output
params = ['--json', '--raw', '--list-packets', data_path('test_list_packets/ecc-p256-pub.asc')]
params = ['--json', '--raw', '--list-packets', data_path(
'test_list_packets/ecc-p256-pub.asc')]
ret, out, err = run_proc(RNP, params)
if ret != 0:
raise_err('json raw packet listing failed', err)
compare_file_ex(data_path('test_list_packets/list_json_raw.txt'), out, 'json raw listing mismatch')
compare_file_ex(data_path('test_list_packets/list_json_raw.txt'), out,
'json raw listing mismatch')
# List packets with all values, JSON output
params = ['--json', '--raw', '--list-packets', data_path('test_list_packets/ecc-p256-pub.asc'), '--mpi', '--grips']
params = ['--json', '--raw', '--list-packets', data_path(
'test_list_packets/ecc-p256-pub.asc'), '--mpi', '--grips']
ret, out, err = run_proc(RNP, params)
if ret != 0:
raise_err('json all listing failed', err)
compare_file_ex(data_path('test_list_packets/list_json_all.txt'), out, 'json all listing mismatch')
compare_file_ex(data_path('test_list_packets/list_json_all.txt'), out,
'json all listing mismatch')
return
def test_debug_log(self):
run_proc(RNPK, ['--homedir', data_path('keyrings/1'), '--list-keys', '--debug', '--all'])
run_proc(RNPK, ['--homedir', data_path('keyrings/2'), '--list-keys', '--debug', '--all'])
run_proc(RNPK, ['--homedir', data_path('keyrings/3'), '--list-keys', '--debug', '--all'])
run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'), '--list-keys', '--debug', '--all'])
run_proc(RNPK, ['--homedir', data_path('test_stream_key_load/g10'),
'--list-keys', '--debug', '--all'])
return
def test_pubring_loading(self):
@ -1513,12 +1646,15 @@ class Encryption(unittest.TestCase):
- different hash algorithms where applicable
TODO:
Tests in this test case should be splitted into many algorithm-specific tests (potentially auto generated)
Reason being - if you have a problem with BLOWFISH size 1000000, you don't want to wait until everything else gets
Tests in this test case should be splitted into many algorithm-specific tests
(potentially auto generated)
Reason being - if you have a problem with BLOWFISH size 1000000, you don't want
to wait until everything else gets
tested before your failing BLOWFISH
'''
# Ciphers list tro try during encryption. None will use default
CIPHERS = [None, 'AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128', 'CAMELLIA192', 'CAMELLIA256', 'IDEA', '3DES', 'CAST5', 'BLOWFISH']
CIPHERS = [None, 'AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128', 'CAMELLIA192',
'CAMELLIA256', 'IDEA', '3DES', 'CAST5', 'BLOWFISH']
SIZES = [20, 40, 120, 600, 1000, 5000, 20000, 150000, 1000000]
# Compression parameters to try during encryption(s)
Z = [[None, 0], ['zip'], ['zlib'], ['bzip2'], [None, 1], [None, 9]]
@ -1545,7 +1681,8 @@ class Encryption(unittest.TestCase):
def tearDown(self):
clear_workfiles()
# Encrypt cleartext file with GPG and decrypt it with RNP, using different ciphers and file sizes
# Encrypt cleartext file with GPG and decrypt it with RNP,
# using different ciphers and file sizes
def test_file_encryption__gpg_to_rnp(self):
for size, cipher in zip(Encryption.SIZES_R, Encryption.CIPHERS_R):
gpg_to_rnp_encryption(size, cipher)
@ -1566,14 +1703,17 @@ class Encryption(unittest.TestCase):
rnp_sym_encryption_rnp_to_gpg(size, cipher, z)
def test_sym_encryption__rnp_aead(self):
AEAD_C = list_upto(['AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128', 'CAMELLIA192', 'CAMELLIA256'], Encryption.RUNS)
AEAD_C = list_upto(['AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128',
'CAMELLIA192', 'CAMELLIA256'], Encryption.RUNS)
AEAD_M = list_upto([None, 'eax', 'ocb'], Encryption.RUNS)
AEAD_B = list_upto([None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 18, 24, 30, 40, 50, 56], Encryption.RUNS)
AEAD_B = list_upto([None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 18,
24, 30, 40, 50, 56], Encryption.RUNS)
usegpg = gpg_supports_aead()
# Encrypt and decrypt cleartext using the AEAD
for size, cipher, aead, bits, z in zip(Encryption.SIZES_R, AEAD_C, AEAD_M, AEAD_B, Encryption.Z_R):
for size, cipher, aead, bits, z in zip(Encryption.SIZES_R, AEAD_C,
AEAD_M, AEAD_B, Encryption.Z_R):
rnp_sym_encryption_rnp_aead(size, cipher, z, [aead, bits], usegpg)
def test_encryption_multiple_recipients(self):
@ -1587,7 +1727,8 @@ class Encryption(unittest.TestCase):
gpg_import_pubring()
gpg_import_secring()
KEYPSWD = tuple((t1, t2) for t1 in range(len(USERIDS) + 1) for t2 in range(len(PASSWORDS) + 1))
KEYPSWD = tuple((t1, t2) for t1 in range(len(USERIDS) + 1)
for t2 in range(len(PASSWORDS) + 1))
KEYPSWD = list_upto(KEYPSWD, Encryption.RUNS)
if gpg_supports_aead():
AEADS = list_upto([None, [None], ['eax'], ['ocb']], Encryption.RUNS)
@ -1638,7 +1779,8 @@ class Encryption(unittest.TestCase):
USERIDS = ['enc-sign1@rnp', 'enc-sign2@rnp', 'enc-sign3@rnp']
KEYPASS = ['encsign1pass', 'encsign2pass', 'encsign3pass']
PASSWORDS = ['password1', 'password2', 'password3']
AEAD_C = list_upto(['AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128', 'CAMELLIA192', 'CAMELLIA256'], Encryption.RUNS)
AEAD_C = list_upto(['AES', 'AES192', 'AES256', 'TWOFISH', 'CAMELLIA128',
'CAMELLIA192', 'CAMELLIA256'], Encryption.RUNS)
# Generate multiple keys and import to GnuPG
for uid, pswd in zip(USERIDS, KEYPASS):
rnp_genkey_rsa(uid, 1024, pswd)
@ -1647,7 +1789,8 @@ class Encryption(unittest.TestCase):
gpg_import_secring()
SIGNERS = list_upto(range(1, len(USERIDS) + 1), Encryption.RUNS)
KEYPSWD = tuple((t1, t2) for t1 in range(1, len(USERIDS) + 1) for t2 in range(len(PASSWORDS) + 1))
KEYPSWD = tuple((t1, t2) for t1 in range(1, len(USERIDS) + 1)
for t2 in range(len(PASSWORDS) + 1))
KEYPSWD = list_upto(KEYPSWD, Encryption.RUNS)
if gpg_supports_aead():
AEADS = list_upto([None, [None], ['eax'], ['ocb']], Encryption.RUNS)
@ -1669,7 +1812,8 @@ class Encryption(unittest.TestCase):
z = ZS[i]
cipher = AEAD_C[i]
rnp_encrypt_and_sign_file(src, dst, recipients, passwords, signers, signpswd, aead, cipher, z)
rnp_encrypt_and_sign_file(src, dst, recipients, passwords, signers,
signpswd, aead, cipher, z)
# Decrypt file with each of the keys, we have different password for each key
for pswd in KEYPASS[:keynum]:
gpg_decrypt_file(dst, dec, pswd)
@ -1802,7 +1946,8 @@ class SignDefault(unittest.TestCase):
class Encrypt(unittest.TestCase, TestIdMixin, KeyLocationChooserMixin):
def _encrypt_decrypt(self, e1, e2):
key_id = "".join(self.id().split('.')[1:3])
keyfile, input, enc_out, dec_out = reg_workfiles(self.test_id, '.gpg', '.in', '.enc', '.dec')
keyfile, input, enc_out, dec_out = reg_workfiles(self.test_id, '.gpg',
'.in', '.enc', '.dec')
random_text(input, 0x1337)
if not self.operation_key_location and not self.operation_key_gencmd:
@ -1853,13 +1998,13 @@ class EncryptElgamal(Encrypt):
def do_test_encrypt(self, sign_key_size, enc_key_size):
pfx = EncryptElgamal.key_pfx(sign_key_size, enc_key_size)
self.operation_key_location = tuple((key_path(pfx,False), key_path(pfx,True)))
self.operation_key_location = tuple((key_path(pfx, False), key_path(pfx, True)))
self.rnp.userid = self.gpg.userid = pfx+"@example.com"
self._encrypt_decrypt(self.gpg, self.rnp)
def do_test_decrypt(self, sign_key_size, enc_key_size):
pfx = EncryptElgamal.key_pfx(sign_key_size, enc_key_size)
self.operation_key_location = tuple((key_path(pfx,False), key_path(pfx,True)))
self.operation_key_location = tuple((key_path(pfx, False), key_path(pfx, True)))
self.rnp.userid = self.gpg.userid = pfx+"@example.com"
self._encrypt_decrypt(self.rnp, self.gpg)
@ -1899,15 +2044,18 @@ class EncryptEcdh(Encrypt):
RNP_GENERATE_ECDH_ECDSA_PATTERN = "19\n{0}\n"
def test_encrypt_nistP256(self):
self.operation_key_gencmd = EncryptEcdh.GPG_GENERATE_ECDH_ECDSA_PATTERN.format("nistp256", self.rnp.userid)
self.operation_key_gencmd = EncryptEcdh.GPG_GENERATE_ECDH_ECDSA_PATTERN.format(
"nistp256", self.rnp.userid)
self._encrypt_decrypt(self.gpg, self.rnp)
def test_encrypt_nistP384(self):
self.operation_key_gencmd = EncryptEcdh.GPG_GENERATE_ECDH_ECDSA_PATTERN.format("nistp384", self.rnp.userid)
self.operation_key_gencmd = EncryptEcdh.GPG_GENERATE_ECDH_ECDSA_PATTERN.format(
"nistp384", self.rnp.userid)
self._encrypt_decrypt(self.gpg, self.rnp)
def test_encrypt_nistP521(self):
self.operation_key_gencmd = EncryptEcdh.GPG_GENERATE_ECDH_ECDSA_PATTERN.format("nistp521", self.rnp.userid)
self.operation_key_gencmd = EncryptEcdh.GPG_GENERATE_ECDH_ECDSA_PATTERN.format(
"nistp521", self.rnp.userid)
self._encrypt_decrypt(self.gpg, self.rnp)
def test_decrypt_nistP256(self):
@ -2036,17 +2184,17 @@ class SignDSA(Sign):
RNP_GENERATE_DSA_PATTERN = "17\n{0}\n"
@staticmethod
def key_pfx(p): return "GnuPG_dsa_elgamal_%d_%d" % (p,p)
def key_pfx(p): return "GnuPG_dsa_elgamal_%d_%d" % (p, p)
def do_test_sign(self, p_size):
pfx = SignDSA.key_pfx(p_size)
self.operation_key_location = tuple((key_path(pfx,False), key_path(pfx,True)))
self.operation_key_location = tuple((key_path(pfx, False), key_path(pfx, True)))
self.rnp.userid = self.gpg.userid = pfx+"@example.com"
self._sign_verify(self.rnp, self.gpg)
def do_test_verify(self, p_size):
pfx = SignDSA.key_pfx(p_size)
self.operation_key_location = tuple((key_path(pfx,False), key_path(pfx,True)))
self.operation_key_location = tuple((key_path(pfx, False), key_path(pfx, True)))
self.rnp.userid = self.gpg.userid = pfx+"@example.com"
self._sign_verify(self.gpg, self.rnp)
@ -2095,18 +2243,18 @@ class EncryptSignRSA(Encrypt, Sign):
RNP_GENERATE_RSA_PATTERN = "1\n{0}\n"
@staticmethod
def key_pfx(p): return "GnuPG_rsa_%d_%d" % (p,p)
def key_pfx(p): return "GnuPG_rsa_%d_%d" % (p, p)
def do_encrypt_verify(self, key_size):
pfx = EncryptSignRSA.key_pfx(key_size)
self.operation_key_location = tuple((key_path(pfx,False), key_path(pfx,True)))
self.operation_key_location = tuple((key_path(pfx, False), key_path(pfx, True)))
self.rnp.userid = self.gpg.userid = pfx+"@example.com"
self._encrypt_decrypt(self.gpg, self.rnp)
self._sign_verify(self.gpg, self.rnp)
def do_rnp_decrypt_sign(self, key_size):
pfx = EncryptSignRSA.key_pfx(key_size)
self.operation_key_location = tuple((key_path(pfx,False), key_path(pfx,True)))
self.operation_key_location = tuple((key_path(pfx, False), key_path(pfx, True)))
self.rnp.userid = self.gpg.userid = pfx+"@example.com"
self._encrypt_decrypt(self.rnp, self.gpg)
self._sign_verify(self.rnp, self.gpg)
@ -2131,6 +2279,8 @@ def test_suites(tests):
if __name__ == '__main__':
main = unittest.main
if not hasattr(main, 'USAGE'):
main.USAGE = ''
main.USAGE += ''.join([
"\nRNP test client specific flags:\n",
" -w,\t\t Don't remove working directory\n",

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

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/env python
import tempfile
import sys

Двоичные данные
third_party/rnp/src/tests/data/test_forged_keys/dsa-eg-pub-forged-key.pgp поставляемый

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

Двоичные данные
third_party/rnp/src/tests/data/test_forged_keys/ecc-25519-pub-future-cert-malf-bind.pgp поставляемый Normal file

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

Двоичные данные
third_party/rnp/src/tests/data/test_forged_keys/ecc-p256-pub-no-cert-malf-binding.pgp поставляемый Normal file

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

Двоичные данные
third_party/rnp/src/tests/data/test_key_validity/alice-sign-sub-pub.pgp поставляемый Normal file

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

Двоичные данные
third_party/rnp/src/tests/data/test_key_validity/alice-sign-sub-sec.pgp поставляемый Normal file

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

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

@ -0,0 +1,3 @@
Hello, world!

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

@ -0,0 +1,17 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Hello, world!
-----BEGIN PGP SIGNATURE-----
Version: rnp 0.9.0+git20200420.739.148391d
wnsEARYIACMWIQRz7cyRGa/I4tu9zeUEUUCWaf/ePAUCXqBD+QUDAAAAAAAKCRAEUUCWaf/ePAA4
AQCab1d6mRcCdEmsIuipCsNHdpEI5Pxcz4DtnOx6GQLL3AD+JlsN4VDfzZiOXY5cDCGmkBgcxMYA
ERpgLB46Y2iCKgbCewQBEwgAIxYhBM/lsBS+5D2dJPPvOCLzohfA5DnLBQJeoEP5BQMAAAAAAAoJ
ECLzohfA5DnLSzAA/A/oRyERJXtKiFiZ6hq4esWMcM7eShnhW2cFaT1Og/NAAQDcU5vOxpu3LNdH
wgpXa7eh2M1O04RHfFrsgO1Pvw8UJg==
=BeZD
-----END PGP SIGNATURE-----

Двоичные данные
third_party/rnp/src/tests/data/test_key_validity/case8/primary.pgp поставляемый Normal file

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

Двоичные данные
third_party/rnp/src/tests/data/test_key_validity/case8/pubring.gpg поставляемый Normal file

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

Двоичные данные
third_party/rnp/src/tests/data/test_key_validity/case8/subkey-no-sig.pgp поставляемый Normal file

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

Двоичные данные
third_party/rnp/src/tests/data/test_key_validity/case8/subkey.pgp поставляемый Normal file

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

Двоичные данные
third_party/rnp/src/tests/data/test_key_validity/case9/pubring.gpg поставляемый Normal file

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

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

@ -35,3 +35,13 @@ Case7:
Keys Alice [pub, sub]
Alice subkey has revocation signature by Alice
Result: Alice [valid], Alice sub [invalid]
Case8:
Keys Alice [pub, sub]
Userid is stripped from the key, but it still has valid subkey binding
Result: Alice [valid], Alice sub[valid]
Case9:
Keys Alice [pub, sub]
Alice key has two self-signatures, one which expires key and second without key expiration.
Result: Alice [valid], Alice sub[valid]

Двоичные данные
third_party/rnp/src/tests/data/test_messages/message_mdc_8k_1.pgp поставляемый Normal file

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

Двоичные данные
third_party/rnp/src/tests/data/test_messages/message_mdc_8k_2.pgp поставляемый Normal file

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

Двоичные данные
third_party/rnp/src/tests/data/test_messages/message_mdc_8k_cut1.pgp поставляемый Normal file

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

Двоичные данные
third_party/rnp/src/tests/data/test_messages/message_mdc_8k_cut22.pgp поставляемый Normal file

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

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

@ -9,16 +9,16 @@ Wf4zSDhsEabUFJn2HoBdSoObcDX3DbBLP4GV7KzBDqJ0ZYfyL92Q58wOs5Q8ZDVP
v41PvEijwVrgNDq02LYxcHgNDAJ++eGOxQdySb3Blo56AorS3xsVtIXFFlzMFB0j
X0lUIeGEj5iKs4xpbRr/EE+m0B70fg2Yn/XpslUnOgboaNp/mZ5T4Zpe1kz/jDV4
aNZ3p3l2DxxF8AUAEQEAAbQWdGVzdF9zdHJlYW1fc2lnbmF0dXJlc4kB1AQTAQgA
PhYhBHpg5nEXn5uSD2R4olhzvXOOV1OYBQJau41QAhsDBQkDwmcABQsJCAcCBhUK
CQgLAgQWAgMBAh4BAheAAAoJEFhzvXOOV1OYt5wL/iwz9BqzPpsGzTMtuCxGlUt5
A1p0aOwK6hD8oDlW5Tq9fuJwKrf0bSen5MPRTs7tkRQ5loriRiqwrgqggxbf2wJx
bFM3p3OF/CO1NMRBeCQCr37hKmtyPv3rmSHRhdeW6IdA5RS5I+UqgUZ18UF9f5va
zM49pflxeDLq16388gcep8pnppw8J0XBFzxW4KWEGLxto1LElq5SJzdTTwQiN2cZ
XmDChFyyQhesxY3qosV2jtIJktLT9Pl1qmxr/wwJf38J5DKmvJeisAl55SahN9l1
owe2ACHQuE9L0HpjxYYxvmFeing0eydDyU10RVgavdI6+ztfVas5f38zy6r3uxX+
mSbV/w4LELvT0jmTAxpVM1O9N7pB71xKypTfsMNEOxi1fWx+/bpB6GVy319JF4aE
JfJYO8rAMWn3UpvY8FaxuCnsDudmpwEvzgOHhr+EOyWlWMbpfC+vtFXncPjEPn7R
lRVy5CkSL+WidtcRmI82iG8hfG3PcpFryea8zMTKCLkBjQRau41QAQwAwB/4Oa2w
PgIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYhBHpg5nEXn5uSD2R4olhzvXOO
V1OYBQJekHJ9BQkWoOgtAAoJEFhzvXOOV1OYdCUMALQ5AsHoE+RU66Qs1qWxQK9k
R7wd0j3yLs/l9eUElpXFz0W/ZRWR2bZ9aO8fuCEQTXPgNtdGBG06fCB/MrpTCwoE
ScUTlz0jGqC8CqbjfV6a92abk+9fXJkYcWyCjFJ0nWzQSSLOlNJ5xesqBB+yBNx7
xyWuggnTcg5F1IbiVN4R3yhKboUZu2nvXIBJVl/JYT5f0jQUAeYLsalmF6Ug6mW3
yVR2wvIlvA5BGlr3qJrIZH22QRPNOfwKZorhPvzD1yj/CXlV4zDDl2TjlcuAkcsT
mqEq+gg/PkLsCpEd1rHIwbplCJiWAxTZLchw49VkGvWAFsiXKCfaWkHZaJpTbTfP
vXppxeJ6VCt/+jU7x8KvRXyqWt45OqIbgs+mi9X4VXqLGXORh4auN6vT/V3uLTOU
1rftvc6mEvcYoKVGNutKcQwfl+MJwfMcjAtDAsov8V6CNDJYGMBZVI6wjh6gt34O
LjlhHM/znBU+FTtPyjSAOvD2SR3oQyVr5gSKVtlPBrkBjQRau41QAQwAwB/4Oa2w
4qupz0+KCmmutEezSKZkf7xZ7UFO87X4hYdoyOUfmtnz4jjA6V5KpZ8DMfrEB9bm
vfHaQBrCdASxspfXDAXfZCV8UqyP+RBItfqdT/tlPxd1uWVqO8pwd0UvXgDICiXy
mCmUOsJ8sajI0X7yN+PjDGoGrUbT8sXpOdGD0aG5ARnaNr9zKa/7RiEaLt8SGdAt
@ -27,15 +27,15 @@ NYMeTk33YoRDlhWWepLYkKZ4Tkrq9A3E/5WjJcFP5NuG8pSM7i+T9glRsZCUH0gI
BhbzTwehQZ3ZM6Rj0aCiFrxBCfzrhjM9PXiJhXwJmV2vCVW2GQZndkF2JwAcAAsF
5mzQD/ylkVLvTg4evNfiFTVQog8nLV0ZyKmodTSUWJCBVgzFP1IuHMbObeAWQF8x
jO69SGt4iOGQw68JljCPBJ8u6N7GMY81mTY/36tWd5pIxOLnAbpodl1DABEBAAGJ
AbwEGAEIACYWIQR6YOZxF5+bkg9keKJYc71zjldTmAUCWruNUAIbDAUJA8JnAAAK
CRBYc71zjldTmBliDACYyguYp9V80mApoM9cdswJCSJu5TpAv+fP+hcekLE0I7wq
qs7+zd0vasrReemgMMA9gx2IbSUZxWPUSoZloJsxcoBfEjlfoNNRXn2X9Hq7NUhu
19gMdwUxtnyd4dOIleYqk93QkydTeqciI+xZ0s2lmiOps0FDgKLWAbNdC/kWOp5x
GHx+Dy9D+cM+4YxjfBnxplG3qreY5Vmu2tlYTXG41LjJHpXL0LOQXdVf6ZdcVdQ5
CCynd583xL9fjxGtAoNYV5LK/1qAZuqFVSk/R9eEy2664W/Fj4I5LlH/UQIfcTdl
ItY+/5mFa0CK7/7uucy7zfIwILx3M9nAvzbFaTdDP7ZBOO6xkeQE22WOMYrcGGkr
lPueHq/gbu/4fl1XHyl4oHJZdqTaI9a9vwO/342ct+y9agtpkooSpljDavVSPiO+
wWd45g52HsY/bF/A7qv1e7ucH11elQgUXW6Q8kGvTy/FYMWjk5tV+mokI/k6rupt
SEvTyvqqYIWvhPXmkI0=
=C3aD
AbwEGAEIACYCGwwWIQR6YOZxF5+bkg9keKJYc71zjldTmAUCXpBymQUJFqDoSQAK
CRBYc71zjldTmOHODACQHml5YT4hsNN4OLP6xNdEKCCjLfY7V1EKYZZU671vYTQn
qIRTGhNB18FATHJwONMjMegsu/8K67V3acnW7cszUbZDC1OMC7Mo0qFHvysfbxbq
4Pb10QYtqvmla8nerbKGKqxm32CRYZf2qZ4pXG/7MvE5aAQPXR+cBgByU9EHOB5K
t9NwYm7MEZyOSNvcRaJIN1aeS8cur5veRoLLEWYhBF/FrOusCLvkupQ/rqnsqr/D
IHaxjHFpSwxAHan8VxkeHsxZNTYb9eejmXTBUrqePARGyuHiqCK7w0fv/RW+mXbn
UDJl+NIg2F0oMcsoqj2F74IWkcn7X7FMP2XQv99PuAgVd9q1XhxDXSBUyXCT+E41
hmR4rtdQRg8JiJ4RZKE8arDjRVXZdaiNMW9J5vjWrlyvqLiVyNmyyHw63LXNO0cN
Qv4qz+S5gir8JAHYzZFnjvisll1Ur9JSQWyg97OB6dsIN7Im6sJOcjpkpHgA5v+9
hMHj3/yuwMXx6aMHF1A=
=zbzp
-----END PGP PUBLIC KEY BLOCK-----

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

@ -8,38 +8,38 @@ bxFGBMeUG66wv4L/+LPWdbt+v22vFTZTdz9KEEgdbYFgSA1Y1CoGgryNwUajbTNa
Wf4zSDhsEabUFJn2HoBdSoObcDX3DbBLP4GV7KzBDqJ0ZYfyL92Q58wOs5Q8ZDVP
v41PvEijwVrgNDq02LYxcHgNDAJ++eGOxQdySb3Blo56AorS3xsVtIXFFlzMFB0j
X0lUIeGEj5iKs4xpbRr/EE+m0B70fg2Yn/XpslUnOgboaNp/mZ5T4Zpe1kz/jDV4
aNZ3p3l2DxxF8AUAEQEAAf4HAwJnOWbrDVPUsMKs7NrQhmnmA68peKqJz2c5mUqo
jFxyhmK/vGieqWlYxDLHK7QvnBHfNUDC+rEQhplarLCbqQRZXv6mbQhz36tq4aUL
JOJoaDdsA/F0gtDJSEI3DurnEuYUBjgYqbJ4oGcJh1OseeKZCoQwjL4+b415TXui
6kbU47rJMMUyOyrBObCPZNVIIPoE9xouAJRDsvK2BBbU5d+Au1pyydF6HtHrMjUv
LkGD98A99G/T5ykjpwFrTf9LWRcgC1wj7tMkf6hmCZOZZQrAsc2bTkBIC/qyaWRb
DKc0HFsf5/ZK3/KrqKLvahzJ8vCBz1onBVil944YFIF8W4/pSgfNcQ2jWzu3mCKn
U+cFEoQig2Z9VEpkgeV39VW0OVYcLZF+5E7LudWScP81GA+pPeGTY6wXHJotlXi+
wT6NLsf+IiA51cxWfUGR0JD1NGynfgMLB2Xl5ajZjJPEnQmA26VG9oYbhD4+HszT
YbcOCVXxWlwaZex0quk+n/zREHCLa7NdTJVDTQohGRGXC0Hko0x09zoOBkt8J87h
woD5Wxk/QxgurWL093nDl58oTvx89KK9mcdkCZ8iDC1DuiBcIg6MsnlbPKva/lrA
FxBtYO7QbsX750kejrp0rcA2kj/+1Gr7kTzqa9EXj18zf/Bc6DKkkScpIg4Q6/+6
lxzoyBuVwAjT2XUYgNYUDpjjFgb0adEaNX7r18RuzGQ4P8NZ3tt0UGXrhUL7tgCW
aEAQdLtpmBhEk78A1Jt4EPArI9KBIZgwiiVmFWQSzfLUNtwWcROD52021AlSiukW
8yHq8vj/tziOUY9eTo5ghDN9d0nodDocSmfkH1X+nG2+Qxr3ksGwsN4haboslWLZ
vNvuQLLXQNxj8HhiWAVeCtc0LSatNZNUDli/BD8Z2KQ2FskCfHT7UVZt5ruOO48U
tNuOKcAszrNZXKfRf1u3rClfRKIwZItzXchTkVF1BsDT++Pe0D9qlQ8LPjQwqYZM
WWgJq2FrGE/FLP0MidKqyUrg5KOWIx6yNFPo01GbUJjuSVwnWBKFmN5/XKtXmglh
yVb+Wy2xABStwipQkEito3QRtBXnxvyfDjW+gtQh52vb8UDXJLPWCmNHKfaxXLb7
Liu1kRl/qP5JIjX5rCBTXyRJXt3heLGOHi5jD9oig4iQADIGk6IapnJ2c4qGlTye
7itOU7l2R8sKOEAWkxA4XazLiOYOuThrw2dXheuuHTPgDj2E+J9eGuFrtAcUEm77
7PddE4YjDjDXGidorru1feF/z86XeN7FOYhGwmBax4XaFYmW0HTOBSjgi3uAnlGd
jmG9GhPq7KYG8unPaUcIJuFCk7ZVyKfPtBZ0ZXN0X3N0cmVhbV9zaWduYXR1cmVz
iQHUBBMBCAA+FiEEemDmcRefm5IPZHiiWHO9c45XU5gFAlq7jVACGwMFCQPCZwAF
CwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQWHO9c45XU5i3nAv+LDP0GrM+mwbN
My24LEaVS3kDWnRo7ArqEPygOVblOr1+4nAqt/RtJ6fkw9FOzu2RFDmWiuJGKrCu
CqCDFt/bAnFsUzenc4X8I7U0xEF4JAKvfuEqa3I+/euZIdGF15boh0DlFLkj5SqB
RnXxQX1/m9rMzj2l+XF4MurXrfzyBx6nymemnDwnRcEXPFbgpYQYvG2jUsSWrlIn
N1NPBCI3ZxleYMKEXLJCF6zFjeqixXaO0gmS0tP0+XWqbGv/DAl/fwnkMqa8l6Kw
CXnlJqE32XWjB7YAIdC4T0vQemPFhjG+YV6KeDR7J0PJTXRFWBq90jr7O19Vqzl/
fzPLqve7Ff6ZJtX/DgsQu9PSOZMDGlUzU703ukHvXErKlN+ww0Q7GLV9bH79ukHo
ZXLfX0kXhoQl8lg7ysAxafdSm9jwVrG4KewO52anAS/OA4eGv4Q7JaVYxul8L6+0
Vedw+MQ+ftGVFXLkKRIv5aJ21xGYjzaIbyF8bc9ykWvJ5rzMxMoInQWGBFq7jVAB
aNZ3p3l2DxxF8AUAEQEAAf4HAwIVPI0CbfDyq+TuIyTWilgZSWAym9yP2zRCaNTU
lixcJLELTQPR2Qy2SNfzu7aGEY7NpA0rHG6YOaFUhvoXLFRbzZ5OiLawurz9zk2I
NrgD+10j57b0FNGmofsu5K4/0YbTyzls/TKVJAMxqXvtT9z1Zw4XywferO+PMIba
0Oh14C7lIWEI5K5/iR6TC1ob7L/UyQ4/OK/1J555eOsN8/SIk4BZsD8qPg1RnL0c
sJrzMvv69sBYOIFpb9U9Fu7AOwRWEzwZaCC1xhyPemOF3gZ1FKv3N/WEBOJvjyAZ
XGltS4BUwSpXDNmHvQn5GzIsY54bY8eKlLrBudrrXetuWAko1a65FzCwVWONyr5v
rOykS7fsLgRHj7fESqooTNNRd64WnUFBWalBqArSKTcswXEfLQaS7O2ifXmQVMLm
RiA0gS5j3Jz5l2W8YFwzrShEsH+mKUPjDkIDYcqkyMKqVZzr1HlfbDOpfzIrknAz
NQYeqWYiJCGGNPTqgFJQnGczcgkabClR85rXWuLJ78cr9pdC5noJzp2597vuaD59
eh9yW2+prAcHwUK9ySv5orLUEGO2TAHEg/OHAcFQ0Q2dRlH1MQNeCUTD3i24wl/8
MtVs+ZlB7ZWp7EpEtyt2o6cT0Kw+GhqLKt5F8mRImu2NAmjL5Fp4UpXbLz3xPKZ1
S+0Z5kWspzmboO0A9cE4mbCwOp3IrxaylWbo1CY4cgmMbxaOc6lIExd1EqArg7/b
rFAjOKRk/dV1hZ5Gjf54BuFu+zPbttvz5HWMbsL1NlLSBC37bdGisL6jGL+SaZwL
FLBzxzqHrR2tJLSomS7hy+hP11XvdQV2LHvFDaqZH5CVR28AG0YPb70YeFWWaTcs
WSqcs/plXqbfDb1pA6fq2ILzyJvJ+4Tg4vmW3kPE2lqGdQUo20BxH6ZvuH1k7RVG
JpO5U1D+8slTfZH5l90KujKRUEyqqjEj6F6r+mKYYoMJZ8+q+8QzoXyavX25Z3pm
ST6jvOhigmeYkZpAPi91qGujC4giNf0iqc5H8vnb/K15aiyBPCtAYrv0pbu17Hkf
giRWwExSCJr0hm/BlCEFc8rWUzFhnNFW9BCl8PUpgxZy4rvTUr/hlJobuDe8AbxJ
bKdOg2rhqgBU9MezUSkuWMaKYO2Cm/W4Awn+EajZOXubH/NwSkbrbMQ/NhZ2Mpuq
M/PrsCrEu8gYVJb3OzxAUL3cZD08+uSe41C66jaBtezFfWFPaDRTMIHcRFUeixtd
XEiUUHwe1GKwvvbPWr+hbKSfwMOVGVYJ3R7H8rSs8k7I4gaocp8h+Dy+6NnZGXiM
LewOsSVgj8E5J9Z0l6IeWdWP4G7u4qCOtBZ0ZXN0X3N0cmVhbV9zaWduYXR1cmVz
iQHUBBMBCAA+AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAFiEEemDmcRefm5IP
ZHiiWHO9c45XU5gFAl6Qcn0FCRag6C0ACgkQWHO9c45XU5h0JQwAtDkCwegT5FTr
pCzWpbFAr2RHvB3SPfIuz+X15QSWlcXPRb9lFZHZtn1o7x+4IRBNc+A210YEbTp8
IH8yulMLCgRJxROXPSMaoLwKpuN9Xpr3ZpuT719cmRhxbIKMUnSdbNBJIs6U0nnF
6yoEH7IE3HvHJa6CCdNyDkXUhuJU3hHfKEpuhRm7ae9cgElWX8lhPl/SNBQB5gux
qWYXpSDqZbfJVHbC8iW8DkEaWveomshkfbZBE805/ApmiuE+/MPXKP8JeVXjMMOX
ZOOVy4CRyxOaoSr6CD8+QuwKkR3WscjBumUImJYDFNktyHDj1WQa9YAWyJcoJ9pa
QdlomlNtN8+9emnF4npUK3/6NTvHwq9FfKpa3jk6ohuCz6aL1fhVeosZc5GHhq43
q9P9Xe4tM5TWt+29zqYS9xigpUY260pxDB+X4wnB8xyMC0MCyi/xXoI0MlgYwFlU
jrCOHqC3fg4uOWEcz/OcFT4VO0/KNIA68PZJHehDJWvmBIpW2U8GnQWGBFq7jVAB
DADAH/g5rbDiq6nPT4oKaa60R7NIpmR/vFntQU7ztfiFh2jI5R+a2fPiOMDpXkql
nwMx+sQH1ua98dpAGsJ0BLGyl9cMBd9kJXxSrI/5EEi1+p1P+2U/F3W5ZWo7ynB3
RS9eAMgKJfKYKZQ6wnyxqMjRfvI34+MMagatRtPyxek50YPRobkBGdo2v3Mpr/tG
@ -48,36 +48,36 @@ IRou3xIZ0C2FyrhzVlZZFZelZV556QvnD4oMSnpOhkEwWebgzpdXzeiE91Ea34il
CVGxkJQfSAgGFvNPB6FBndkzpGPRoKIWvEEJ/OuGMz09eImFfAmZXa8JVbYZBmd2
QXYnABwACwXmbNAP/KWRUu9ODh681+IVNVCiDyctXRnIqah1NJRYkIFWDMU/Ui4c
xs5t4BZAXzGM7r1Ia3iI4ZDDrwmWMI8Eny7o3sYxjzWZNj/fq1Z3mkjE4ucBumh2
XUMAEQEAAf4HAwIJVey/KKWPocL6fOspBqT2URMqaYYU/fyN6cSa0Clx1T+zrcD1
swWZF/Q8Ia+wDLHzMLeYbeWz0wBodpcIpRGSDNbNHAn6GMk4K23UGzMIquvCEvbd
XY7/N032emPBZ61Y2VJ5MuioA9lvG+HRirf/QmagveHAtPBqkjDwjE0nL7MarH7g
bNIHZfpYzywd3WRpvYlRebujkriS40EIAbXC6OWnlOs7srXroSpkbuqUYmx3MTMa
N5cP7DR+uxbiozJHW8k6Cg3MBPbdbfued3Lobc98UCuW6+0J0H8BGzDOT9eGgYQn
mtBaqCjCZqbN4d59Z9rp/qX6kSISZohl05rwjFI0vsi9M4cQApwrb9R7mBqCN1Xm
w0NTUeR9rPDomrpb0sTUzXJbrjdLXqe6RdNbEWvcJeWRxNWbzqlGTr2tmUa34XMg
BprMcRQXVcf7uHVsYCRCixurQTkFfejAVNIYt6x8OHRheR5XGdyakWr/iY4iBAjf
abWDa4huryYD4PtpY0GDzHEyO7trSSPKRnYUIobmye/4LOfcNBC3HCx1suXXgALF
MFMgvMJIRKr5HhbfpkJVYaU8M+R9mswkxyQxaPTO67RWVkIRsQgz4DzVw/sLuv5y
G+bBEgEU95OtCE3CPmXApk2aBzRkoXubw7L5wdTLI9keWClB+cqYsuc5xYUvRswj
qCJWALjE0x48FP+3AmT+0BPTwevhZ77QrZ4nKdlYXrRdoRsHrVCh2srVdCr5a/Ou
6d4lrhTkRZsW+X3uu3gnznVrcJygIKPW/Plw3zI1aFJBMgtFtnrIr+I1k/dlHaVi
tAtfkkszvIupjE28JlfsYsNxSr/nKlC/r+seGuxCUJnKR9Vl55p4ByTkae2aFD94
bPytybrpT/uZi/5evr0cgY4SkFQmzt1BvNdVU1vgi6tsw7NmSClUPZINqzB1SeAP
bx7wAeq5h9dsHMAERgw1fwrqDdVem0wZPX/2VBJlVFZmrDsogv/6XEsQdSS9deCW
gVR3CweHByxvjxdzu+2gZ/EDL6UdXE+X6DhQkUrETAkP+fEN28dPvLFmVPibpdN7
VSpg1qTJIXCY2AHIfrZQzs02J1/vJNaTMGRdAT0ApbNndLeqZK2zaf39+SvagO3/
uxheTDEc0/kovDtq6KRWj1TtbpzsdOphL+o5QMyZKl0oeVITRWoirCi57K2W05xJ
83bEhMYMcmW0enbVWzJ4ilWK1NGgTZvAzLMBYIXXjv+Q6yJA2kjlY6iBH+56XTO7
l/xhvBHLMwdkivvNgAb9Zx7fbFSj0gw9PsMXdwwzXKMtWIqSeptcQUYHFlOlx7DX
Fjw/d5MtDlXxX41l6eeXYYkBvAQYAQgAJhYhBHpg5nEXn5uSD2R4olhzvXOOV1OY
BQJau41QAhsMBQkDwmcAAAoJEFhzvXOOV1OYGWIMAJjKC5in1XzSYCmgz1x2zAkJ
Im7lOkC/58/6Fx6QsTQjvCqqzv7N3S9qytF56aAwwD2DHYhtJRnFY9RKhmWgmzFy
gF8SOV+g01FefZf0ers1SG7X2Ax3BTG2fJ3h04iV5iqT3dCTJ1N6pyIj7FnSzaWa
I6mzQUOAotYBs10L+RY6nnEYfH4PL0P5wz7hjGN8GfGmUbeqt5jlWa7a2VhNcbjU
uMkelcvQs5Bd1V/pl1xV1DkILKd3nzfEv1+PEa0Cg1hXksr/WoBm6oVVKT9H14TL
brrhb8WPgjkuUf9RAh9xN2Ui1j7/mYVrQIrv/u65zLvN8jAgvHcz2cC/NsVpN0M/
tkE47rGR5ATbZY4xitwYaSuU+54er+Bu7/h+XVcfKXigcll2pNoj1r2/A7/fjZy3
7L1qC2mSihKmWMNq9VI+I77BZ3jmDnYexj9sX8Duq/V7u5wfXV6VCBRdbpDyQa9P
L8VgxaOTm1X6aiQj+Tqu6m1IS9PK+qpgha+E9eaQjQ==
=vuN6
XUMAEQEAAf4HAwKHPjD5J2XTROT4F02fJHp3k5ROZ6tELUQnFme5bv71OBmvpyPL
Qag7Ix/ZJzrNdJi6gkii2w6Kd8TzdOESSKL+LimY+wHprev/udy6JGGpPK4EMp61
o3sNR6lDqvKFFgW7rnE6DU7UeyiWv4GCC/aC0ivxQASHdu5IQBZftx/WO+J84xw3
q4Xd4bGn0Dm9CRzd5SoJdVFeuhVTqqhzyu8O8u7VLIRhCwp5cZE6IgJb1f6+B4+x
+gaoWZJwvUqqnJQCKY670qKlyhXEmoILJ7zdG6sVyaeIvJR6lZfvqBnWo4Uu1vL7
uo9GVzCLR0GLaiMR0I9Z1BmeRDVUP9Vbk3P0MxeKcequPbboaDqHtNejxvGeOT1M
QC+6ugHp+vHSSwHxiMJM1b66hBJc6OnQauBugjvro+nsgCOe1+BqWVkJ/ycwPHOB
v3r9TfaqUO/0wAni3x8cLnRQNA5IoIgifzP6zc02styO0QPuNKDMOj/TMNQw668g
W2kZllB+aki42tWZ095eVGtt9hJltLKqGciLfTmBQQvvtmAJyFhVYwsKAGfj1xqz
E6/wCRRu5zQ2y0JUAIeNUVimX+3mFXsb+QxrZOsxh9EGYQxyRKHKkQtCtNzuWLhB
Q2IHNeIlkxptRmq0TvApe2sV06orPqW9oCXULrWNFq0Ur4KD3AuLhZLFK+r2/gj4
grTafzV7b4pWzQQq0ynqXAgkKHRg9eL2CQlfrlMwoteYJZPjEoHTtIW+yi0izXpc
KZYROwyZVEV5x2Mr/yhH/IA6r/mDrnq2L6q1k5OjW6GzOFZg7lYjybq8sHUwzbhe
gbgix/CUZf2Bk3TIGxaiYLnijbT1te9hLpQIdTHdnS/MDPPy3hQWoi1lP0rykypg
yKToeu1UKocuTzwgVHG7GC6XbdsYoqo46TQO22ckAFk68t/50gJFzIILEEqiRHBc
jmmdQGZKZst4fI7nXxE0KuYpSdX9NRIF72vptT+Ag59AOdVRxNHXD78G7vO8zv9i
npJWSOEYWt8gVhbuaOVNoQbE1ox7J3CEoh9vfOFciTWZbVTVKDkFa7f8jld4v6sm
ePV2ol2No2/7aJx+DH78pg32OW+fDD3rasmtC833LLUdyOCSllU4TGpRIU4bhprz
7+CzQfhQrkz0LfS2RizzpAis9BitoizwWLjMrhHN/X5uffKM3J2OjmZ4nCOQUSeW
3BNwzcWLIIoCZ/ior8sh8lexrVVwy/YCJFGZl8S/gkxgjKX5Wiem7UV+92QqNk5N
ogxSwgrwJVieWH17ILTpvDJRJsM3JhhTVhHme/JF6CQGo8J3wUzR6nfNaPhXQrxH
lNcRDiC57AkOlnI7coOs0YkBvAQYAQgAJgIbDBYhBHpg5nEXn5uSD2R4olhzvXOO
V1OYBQJekHKZBQkWoOhJAAoJEFhzvXOOV1OY4c4MAJAeaXlhPiGw03g4s/rE10Qo
IKMt9jtXUQphllTrvW9hNCeohFMaE0HXwUBMcnA40yMx6Cy7/wrrtXdpydbtyzNR
tkMLU4wLsyjSoUe/Kx9vFurg9vXRBi2q+aVryd6tsoYqrGbfYJFhl/apnilcb/sy
8TloBA9dH5wGAHJT0Qc4Hkq303BibswRnI5I29xFokg3Vp5Lxy6vm95GgssRZiEE
X8Ws66wIu+S6lD+uqeyqv8MgdrGMcWlLDEAdqfxXGR4ezFk1Nhv156OZdMFSup48
BEbK4eKoIrvDR+/9Fb6ZdudQMmX40iDYXSgxyyiqPYXvghaRyftfsUw/ZdC/30+4
CBV32rVeHENdIFTJcJP4TjWGZHiu11BGDwmInhFkoTxqsONFVdl1qI0xb0nm+Nau
XK+ouJXI2bLIfDrctc07Rw1C/irP5LmCKvwkAdjNkWeO+KyWXVSv0lJBbKD3s4Hp
2wg3sibqwk5yOmSkeADm/72EwePf/K7AxfHpowcXUA==
=Nabv
-----END PGP PRIVATE KEY BLOCK-----

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

@ -802,10 +802,10 @@ TEST_F(rnp_tests, test_ffi_keygen_json_pair)
rnp_key_handle_t primary = NULL;
{
json_object *jsokey = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(parsed_results, "primary", &jsokey));
assert_int_equal(true, json_object_object_get_ex(parsed_results, "primary", &jsokey));
assert_non_null(jsokey);
json_object *jsogrip = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_int_equal(true, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_non_null(jsogrip);
const char *grip = json_object_get_string(jsogrip);
assert_non_null(grip);
@ -816,10 +816,10 @@ TEST_F(rnp_tests, test_ffi_keygen_json_pair)
rnp_key_handle_t sub = NULL;
{
json_object *jsokey = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(parsed_results, "sub", &jsokey));
assert_int_equal(true, json_object_object_get_ex(parsed_results, "sub", &jsokey));
assert_non_null(jsokey);
json_object *jsogrip = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_int_equal(true, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_non_null(jsogrip);
const char *grip = json_object_get_string(jsogrip);
assert_non_null(grip);
@ -880,10 +880,10 @@ TEST_F(rnp_tests, test_ffi_keygen_json_pair_dsa_elg)
rnp_key_handle_t primary = NULL;
{
json_object *jsokey = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(parsed_results, "primary", &jsokey));
assert_int_equal(true, json_object_object_get_ex(parsed_results, "primary", &jsokey));
assert_non_null(jsokey);
json_object *jsogrip = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_int_equal(true, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_non_null(jsogrip);
const char *grip = json_object_get_string(jsogrip);
assert_non_null(grip);
@ -894,10 +894,10 @@ TEST_F(rnp_tests, test_ffi_keygen_json_pair_dsa_elg)
rnp_key_handle_t sub = NULL;
{
json_object *jsokey = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(parsed_results, "sub", &jsokey));
assert_int_equal(true, json_object_object_get_ex(parsed_results, "sub", &jsokey));
assert_non_null(jsokey);
json_object *jsogrip = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_int_equal(true, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_non_null(jsogrip);
const char *grip = json_object_get_string(jsogrip);
assert_non_null(grip);
@ -960,10 +960,10 @@ TEST_F(rnp_tests, test_ffi_keygen_json_primary)
rnp_key_handle_t primary = NULL;
{
json_object *jsokey = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(parsed_results, "primary", &jsokey));
assert_int_equal(true, json_object_object_get_ex(parsed_results, "primary", &jsokey));
assert_non_null(jsokey);
json_object *jsogrip = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_int_equal(true, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_non_null(jsogrip);
const char *grip = json_object_get_string(jsogrip);
assert_non_null(grip);
@ -1023,10 +1023,10 @@ TEST_F(rnp_tests, test_ffi_keygen_json_sub)
char * primary_grip = NULL;
{
json_object *jsokey = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(parsed_results, "primary", &jsokey));
assert_int_equal(true, json_object_object_get_ex(parsed_results, "primary", &jsokey));
assert_non_null(jsokey);
json_object *jsogrip = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_int_equal(true, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_non_null(jsogrip);
primary_grip = strdup(json_object_get_string(jsogrip));
assert_non_null(primary_grip);
@ -1081,10 +1081,10 @@ TEST_F(rnp_tests, test_ffi_keygen_json_sub)
rnp_key_handle_t sub = NULL;
{
json_object *jsokey = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(parsed_results, "sub", &jsokey));
assert_int_equal(true, json_object_object_get_ex(parsed_results, "sub", &jsokey));
assert_non_null(jsokey);
json_object *jsogrip = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_int_equal(true, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_non_null(jsogrip);
const char *grip = json_object_get_string(jsogrip);
assert_non_null(grip);
@ -2485,10 +2485,10 @@ TEST_F(rnp_tests, test_ffi_keygen_json_sub_pass_required)
char * primary_grip = NULL;
{
json_object *jsokey = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(parsed_results, "primary", &jsokey));
assert_int_equal(true, json_object_object_get_ex(parsed_results, "primary", &jsokey));
assert_non_null(jsokey);
json_object *jsogrip = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_int_equal(true, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_non_null(jsogrip);
primary_grip = strdup(json_object_get_string(jsogrip));
assert_non_null(primary_grip);
@ -2559,10 +2559,10 @@ TEST_F(rnp_tests, test_ffi_keygen_json_sub_pass_required)
rnp_key_handle_t sub = NULL;
{
json_object *jsokey = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(parsed_results, "sub", &jsokey));
assert_int_equal(true, json_object_object_get_ex(parsed_results, "sub", &jsokey));
assert_non_null(jsokey);
json_object *jsogrip = NULL;
assert_int_equal(TRUE, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_int_equal(true, json_object_object_get_ex(jsokey, "grip", &jsogrip));
assert_non_null(jsogrip);
const char *grip = json_object_get_string(jsogrip);
assert_non_null(grip);
@ -3823,7 +3823,7 @@ TEST_F(rnp_tests, test_ffi_key_to_json)
assert_int_equal(rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "grip")),
"20A48B3C61525DCDF8B3B9D82C6BBCF4D8BFB5E5"),
0);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "revoked")), FALSE);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "revoked")), false);
assert_int_equal(json_object_get_int64(get_json_obj(jso, "creation time")), 1511313500);
assert_int_equal(json_object_get_int64(get_json_obj(jso, "expiration")), 0);
// usage
@ -3845,7 +3845,7 @@ TEST_F(rnp_tests, test_ffi_key_to_json)
"FFFA72FC225214DC712D0127172EE13E88AF93B4"),
0);
// public key
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "public key.present")), TRUE);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "public key.present")), true);
assert_int_equal(
rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "public key.mpis.point")),
"04B0C6F2F585C1EEDF805C4492CB683839D5EAE6246420780F063D558"
@ -3853,14 +3853,14 @@ TEST_F(rnp_tests, test_ffi_key_to_json)
"793CEBAE8600BEEF"),
0);
// secret key
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.present")), TRUE);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.present")), true);
assert_int_equal(
rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "secret key.mpis.x")),
"46DE93CA439735F36B9CF228F10D8586DA824D88BBF4E24566D5312D061802C8"),
0);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.locked")), FALSE);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.locked")), false);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.protected")),
FALSE);
false);
// userids
assert_int_equal(json_object_array_length(get_json_obj(jso, "userids")), 1);
assert_int_equal(rnp_strcasecmp(json_object_get_string(json_object_array_get_idx(
@ -3909,7 +3909,7 @@ TEST_F(rnp_tests, test_ffi_key_to_json)
assert_int_equal(rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "grip")),
"FFFA72FC225214DC712D0127172EE13E88AF93B4"),
0);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "revoked")), FALSE);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "revoked")), false);
assert_int_equal(json_object_get_int64(get_json_obj(jso, "creation time")), 1511313500);
assert_int_equal(json_object_get_int64(get_json_obj(jso, "expiration")), 0);
// usage
@ -3926,21 +3926,21 @@ TEST_F(rnp_tests, test_ffi_key_to_json)
// subkey grips
assert_null(get_json_obj(jso, "subkey grips"));
// public key
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "public key.present")), TRUE);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "public key.present")), true);
assert_int_equal(
rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "public key.mpis.point")),
"04E2746BA4D180011B17A6909EABDBF2F3733674FBE00B20A3B857C2597233651544150B"
"896BCE7DCDF47C49FC1E12D5AD86384D26336A48A18845940A3F65F502"),
0);
// secret key
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.present")), TRUE);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.present")), true);
assert_int_equal(
rnp_strcasecmp(json_object_get_string(get_json_obj(jso, "secret key.mpis.x")),
"DF8BEB7272117AD7AFE2B7E882453113059787FBC785C82F78624EE7EF2117FB"),
0);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.locked")), FALSE);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.locked")), false);
assert_int_equal(json_object_get_boolean(get_json_obj(jso, "secret key.protected")),
FALSE);
false);
// userids
assert_null(get_json_obj(jso, "userids"));
// signatures
@ -5502,6 +5502,116 @@ TEST_F(rnp_tests, test_ffi_keys_import)
rnp_ffi_destroy(ffi);
}
TEST_F(rnp_tests, test_ffi_stripped_keys_import)
{
rnp_ffi_t ffi = NULL;
rnp_input_t input = NULL;
assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG"));
/* load stripped key as keyring */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/case8/pubring.gpg"));
assert_rnp_success(rnp_load_keys(ffi, "GPG", input, RNP_LOAD_SAVE_PUBLIC_KEYS));
rnp_input_destroy(input);
/* validate signatures - must succeed */
rnp_op_verify_t verify = NULL;
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/case8/message.txt.asc"));
rnp_output_t output = NULL;
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_ffi_set_pass_provider(ffi, getpasscb, (void *) "password"));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
rnp_input_destroy(input);
rnp_output_destroy(output);
rnp_op_verify_signature_t sig;
/* signature 1 - by primary key */
assert_rnp_success(rnp_op_verify_get_signature_at(verify, 0, &sig));
assert_rnp_success(rnp_op_verify_signature_get_status(sig));
/* signature 2 - by subkey */
assert_rnp_success(rnp_op_verify_get_signature_at(verify, 1, &sig));
assert_rnp_success(rnp_op_verify_signature_get_status(sig));
rnp_op_verify_destroy(verify);
/* load stripped key by parts via import */
assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC));
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/case8/primary.pgp"));
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/test_key_validity/case8/subkey.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
rnp_input_destroy(input);
/* validate signatures - must be valid */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/case8/message.txt.asc"));
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));
rnp_input_destroy(input);
rnp_output_destroy(output);
/* signature 1 - by primary key */
assert_rnp_success(rnp_op_verify_get_signature_at(verify, 0, &sig));
assert_rnp_success(rnp_op_verify_signature_get_status(sig));
/* signature 2 - by subkey */
assert_rnp_success(rnp_op_verify_get_signature_at(verify, 1, &sig));
assert_rnp_success(rnp_op_verify_signature_get_status(sig));
rnp_op_verify_destroy(verify);
/* load stripped key with subkey first */
assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC));
assert_rnp_success(rnp_input_from_path(&input, "data/test_key_validity/case8/subkey.pgp"));
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/test_key_validity/case8/primary.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
rnp_input_destroy(input);
/* validate signatures - must be valid */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/case8/message.txt.asc"));
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));
rnp_input_destroy(input);
rnp_output_destroy(output);
/* signature 1 - by primary key */
assert_rnp_success(rnp_op_verify_get_signature_at(verify, 0, &sig));
assert_rnp_success(rnp_op_verify_signature_get_status(sig));
/* signature 2 - by subkey */
assert_rnp_success(rnp_op_verify_get_signature_at(verify, 1, &sig));
assert_rnp_success(rnp_op_verify_signature_get_status(sig));
rnp_op_verify_destroy(verify);
/* load stripped key without subkey binding */
assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC));
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/case8/primary.pgp"));
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/test_key_validity/case8/subkey-no-sig.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
rnp_input_destroy(input);
/* validate signatures - must be invalid */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/case8/message.txt.asc"));
assert_rnp_success(rnp_output_to_null(&output));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_int_equal(rnp_op_verify_execute(verify), RNP_ERROR_SIGNATURE_INVALID);
rnp_input_destroy(input);
rnp_output_destroy(output);
/* signature 1 - by primary key */
assert_rnp_success(rnp_op_verify_get_signature_at(verify, 0, &sig));
assert_int_equal(rnp_op_verify_signature_get_status(sig), RNP_ERROR_SIGNATURE_INVALID);
/* signature 2 - by subkey */
assert_rnp_success(rnp_op_verify_get_signature_at(verify, 1, &sig));
assert_int_equal(rnp_op_verify_signature_get_status(sig), RNP_ERROR_SIGNATURE_INVALID);
rnp_op_verify_destroy(verify);
rnp_ffi_destroy(ffi);
}
static std::vector<uint8_t>
read_file_to_vector(const char *valid_key_path)
{
@ -6925,10 +7035,27 @@ TEST_F(rnp_tests, test_ffi_secret_sig_import)
assert_rnp_success(rnp_input_from_path(&input, "data/test_key_validity/alice-rev.pgp"));
assert_rnp_success(rnp_import_signatures(ffi, input, 0, NULL));
assert_rnp_success(rnp_input_destroy(input));
/* make sure that key is still unlocked */
assert_rnp_success(rnp_key_is_locked(key_handle, &locked));
assert_false(locked);
/* import subkey */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/alice-sub-sec.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_SECRET_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
/* make sure that primary key is still unlocked */
assert_rnp_success(rnp_key_is_locked(key_handle, &locked));
assert_false(locked);
/* unlock subkey and make sure it is unlocked after revocation */
rnp_key_handle_t sub_handle = NULL;
assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub_handle));
assert_rnp_success(rnp_key_unlock(sub_handle, "password"));
assert_rnp_success(rnp_key_is_locked(sub_handle, &locked));
assert_false(locked);
assert_rnp_success(rnp_key_revoke(sub_handle, 0, "SHA256", "retired", "Custom reason"));
assert_rnp_success(rnp_key_is_locked(sub_handle, &locked));
assert_false(locked);
assert_rnp_success(rnp_key_handle_destroy(sub_handle));
assert_rnp_success(rnp_key_handle_destroy(key_handle));
assert_rnp_success(rnp_ffi_destroy(ffi));
}
@ -7014,3 +7141,358 @@ TEST_F(rnp_tests, test_ffi_rnp_request_password)
assert_rnp_success(rnp_key_handle_destroy(key));
assert_rnp_success(rnp_ffi_destroy(ffi));
}
TEST_F(rnp_tests, test_ffi_key_revoke)
{
rnp_ffi_t ffi = NULL;
rnp_input_t input = NULL;
assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG"));
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));
assert_rnp_success(rnp_input_destroy(input));
rnp_key_handle_t key_handle = NULL;
assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key_handle));
/* check for failure with wrong parameters */
assert_rnp_failure(rnp_key_revoke(NULL, 0, "SHA256", "superseded", "test key revocation"));
assert_rnp_failure(rnp_key_revoke(key_handle, 0, "SHA256", NULL, NULL));
assert_rnp_failure(rnp_key_revoke(key_handle, 0x17, "SHA256", NULL, NULL));
assert_rnp_failure(rnp_key_revoke(key_handle, 0, "Wrong hash", NULL, NULL));
assert_rnp_failure(rnp_key_revoke(key_handle, 0, "SHA256", "Wrong reason code", NULL));
/* attempt to revoke key without the secret */
assert_rnp_failure(rnp_key_revoke(key_handle, 0, "SHA256", "retired", "Custom reason"));
assert_rnp_success(rnp_key_handle_destroy(key_handle));
/* attempt to revoke subkey without the secret */
rnp_key_handle_t sub_handle = NULL;
assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub_handle));
assert_rnp_failure(rnp_key_revoke(sub_handle, 0, "SHA256", "retired", "Custom reason"));
assert_rnp_success(rnp_key_handle_destroy(sub_handle));
/* load secret key */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/alice-sub-sec.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_SECRET_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key_handle));
assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub_handle));
/* wrong password - must fail */
assert_rnp_success(rnp_ffi_set_pass_provider(ffi, getpasscb, (void *) "wrong"));
assert_rnp_failure(rnp_key_revoke(key_handle, 0, "SHA256", "superseded", NULL));
assert_rnp_failure(rnp_key_revoke(sub_handle, 0, "SHA256", "superseded", NULL));
/* unlocked key - must succeed */
bool revoked = false;
assert_rnp_success(rnp_key_is_revoked(key_handle, &revoked));
assert_false(revoked);
assert_rnp_success(rnp_key_unlock(key_handle, "password"));
assert_rnp_success(rnp_key_revoke(key_handle, 0, "SHA256", NULL, NULL));
assert_rnp_success(rnp_key_is_revoked(key_handle, &revoked));
assert_true(revoked);
/* subkey */
assert_rnp_success(rnp_key_is_revoked(sub_handle, &revoked));
assert_false(revoked);
bool locked = true;
assert_rnp_success(rnp_key_is_locked(key_handle, &locked));
assert_false(locked);
assert_rnp_success(rnp_key_revoke(sub_handle, 0, "SHA256", NULL, "subkey revoked"));
assert_rnp_success(rnp_key_is_revoked(sub_handle, &revoked));
assert_true(revoked);
assert_rnp_success(rnp_key_lock(key_handle));
assert_rnp_success(rnp_key_handle_destroy(key_handle));
assert_rnp_success(rnp_key_handle_destroy(sub_handle));
/* correct password provider - must succeed */
assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_SECRET | RNP_KEY_UNLOAD_PUBLIC));
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/alice-sub-sec.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_SECRET_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key_handle));
assert_rnp_success(rnp_ffi_set_pass_provider(ffi, getpasscb, (void *) "password"));
assert_rnp_success(rnp_key_is_revoked(key_handle, &revoked));
assert_false(revoked);
assert_rnp_success(
rnp_key_revoke(key_handle, 0, "SHA256", "superseded", "test key revocation"));
assert_rnp_success(rnp_key_is_revoked(key_handle, &revoked));
assert_true(revoked);
/* make sure FFI locks key back */
assert_rnp_success(rnp_key_is_locked(key_handle, &locked));
assert_true(locked);
assert_rnp_success(rnp_key_handle_destroy(key_handle));
/* repeat for subkey */
assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub_handle));
assert_rnp_success(rnp_key_is_revoked(sub_handle, &revoked));
assert_false(revoked);
assert_rnp_success(rnp_key_revoke(sub_handle, 0, "SHA256", "no", "test sub revocation"));
assert_rnp_success(rnp_key_is_revoked(sub_handle, &revoked));
assert_true(revoked);
assert_rnp_success(rnp_key_handle_destroy(sub_handle));
assert_rnp_success(rnp_ffi_destroy(ffi));
}
TEST_F(rnp_tests, test_ffi_key_set_expiry)
{
rnp_ffi_t ffi = NULL;
rnp_input_t input = NULL;
assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG"));
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));
assert_rnp_success(rnp_input_destroy(input));
/* check edge cases */
assert_rnp_failure(rnp_key_set_expiration(NULL, 0));
rnp_key_handle_t key = NULL;
assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key));
/* cannot set key expiration with public key only */
assert_rnp_failure(rnp_key_set_expiration(key, 1000));
rnp_key_handle_t sub = NULL;
assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub));
assert_rnp_failure(rnp_key_set_expiration(sub, 1000));
assert_rnp_success(rnp_key_handle_destroy(key));
assert_rnp_success(rnp_key_handle_destroy(sub));
/* load secret key */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/alice-sub-sec.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_SECRET_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
uint32_t expiry = 0;
const uint32_t new_expiry = 10 * 365 * 24 * 60 * 60;
assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key));
assert_rnp_success(rnp_key_get_expiration(key, &expiry));
assert_int_equal(expiry, 0);
assert_rnp_success(rnp_key_set_expiration(key, 0));
/* will fail on locked key */
assert_rnp_failure(rnp_key_set_expiration(key, new_expiry));
assert_rnp_success(rnp_key_unlock(key, "password"));
assert_rnp_success(rnp_key_set_expiration(key, new_expiry));
assert_rnp_success(rnp_key_get_expiration(key, &expiry));
assert_int_equal(expiry, new_expiry);
assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub));
/* will succeed on locked subkey since it is not signing one */
assert_rnp_success(rnp_key_set_expiration(sub, 0));
assert_rnp_success(rnp_key_set_expiration(sub, new_expiry * 2));
assert_rnp_success(rnp_key_get_expiration(sub, &expiry));
assert_int_equal(expiry, new_expiry * 2);
/* make sure new expiration times are properly saved */
rnp_output_t keymem = NULL;
rnp_output_t seckeymem = NULL;
assert_rnp_success(rnp_output_to_memory(&keymem, 0));
assert_rnp_success(
rnp_key_export(key, keymem, RNP_KEY_EXPORT_PUBLIC | RNP_KEY_EXPORT_SUBKEYS));
assert_rnp_success(rnp_output_to_memory(&seckeymem, 0));
assert_rnp_success(
rnp_key_export(key, seckeymem, RNP_KEY_EXPORT_SECRET | RNP_KEY_EXPORT_SUBKEYS));
assert_rnp_success(rnp_key_handle_destroy(key));
assert_rnp_success(rnp_key_handle_destroy(sub));
assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET));
uint8_t *keybuf = NULL;
size_t keylen = 0;
assert_rnp_success(rnp_output_memory_get_buf(keymem, &keybuf, &keylen, false));
assert_rnp_success(rnp_input_from_memory(&input, keybuf, keylen, false));
/* load public key */
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key));
assert_rnp_success(rnp_key_get_expiration(key, &expiry));
assert_int_equal(expiry, new_expiry);
assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub));
assert_rnp_success(rnp_key_get_expiration(sub, &expiry));
assert_int_equal(expiry, new_expiry * 2);
assert_rnp_success(rnp_key_handle_destroy(key));
assert_rnp_success(rnp_key_handle_destroy(sub));
assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET));
/* now load exported secret key */
assert_rnp_success(rnp_output_memory_get_buf(seckeymem, &keybuf, &keylen, false));
assert_rnp_success(rnp_input_from_memory(&input, keybuf, keylen, false));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_SECRET_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_output_destroy(seckeymem));
assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key));
assert_rnp_success(rnp_key_get_expiration(key, &expiry));
assert_int_equal(expiry, new_expiry);
assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub));
assert_rnp_success(rnp_key_get_expiration(sub, &expiry));
assert_int_equal(expiry, new_expiry * 2);
assert_rnp_success(rnp_key_handle_destroy(key));
assert_rnp_success(rnp_key_handle_destroy(sub));
/* now unset expiration time back, first loading the public key back */
assert_rnp_success(rnp_output_memory_get_buf(keymem, &keybuf, &keylen, false));
assert_rnp_success(rnp_input_from_memory(&input, keybuf, keylen, false));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_output_destroy(keymem));
/* set primary key expiration */
assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key));
assert_rnp_success(rnp_key_unlock(key, "password"));
assert_rnp_success(rnp_key_set_expiration(key, 0));
assert_rnp_success(rnp_key_get_expiration(key, &expiry));
assert_int_equal(expiry, 0);
assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub));
assert_rnp_success(rnp_key_set_expiration(sub, 0));
assert_rnp_success(rnp_key_get_expiration(sub, &expiry));
assert_int_equal(expiry, 0);
/* let's export them and reload */
assert_rnp_success(rnp_output_to_memory(&keymem, 0));
assert_rnp_success(
rnp_key_export(key, keymem, RNP_KEY_EXPORT_PUBLIC | RNP_KEY_EXPORT_SUBKEYS));
assert_rnp_success(rnp_key_handle_destroy(key));
assert_rnp_success(rnp_key_handle_destroy(sub));
assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET));
assert_rnp_success(rnp_output_memory_get_buf(keymem, &keybuf, &keylen, false));
assert_rnp_success(rnp_input_from_memory(&input, keybuf, keylen, false));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_output_destroy(keymem));
assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key));
assert_rnp_success(rnp_key_get_expiration(key, &expiry));
assert_int_equal(expiry, 0);
assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub));
assert_rnp_success(rnp_key_get_expiration(sub, &expiry));
assert_int_equal(expiry, 0);
assert_rnp_success(rnp_key_handle_destroy(key));
assert_rnp_success(rnp_key_handle_destroy(sub));
/* now try the sign-able subkey */
assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET));
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/alice-sign-sub-pub.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/alice-sign-sub-sec.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_SECRET_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key));
assert_rnp_success(rnp_locate_key(ffi, "keyid", "22F3A217C0E439CB", &sub));
assert_rnp_success(rnp_key_get_expiration(sub, &expiry));
assert_int_equal(expiry, 0);
assert_rnp_failure(rnp_key_set_expiration(sub, new_expiry));
/* now unlock only primary key - should fail */
assert_rnp_success(rnp_key_unlock(key, "password"));
assert_rnp_failure(rnp_key_set_expiration(sub, new_expiry));
/* unlock subkey */
assert_rnp_success(rnp_key_unlock(sub, "password"));
assert_rnp_success(rnp_key_set_expiration(sub, new_expiry));
assert_rnp_success(rnp_key_get_expiration(sub, &expiry));
assert_int_equal(expiry, new_expiry);
assert_rnp_success(rnp_output_to_memory(&keymem, 0));
assert_rnp_success(
rnp_key_export(key, keymem, RNP_KEY_EXPORT_PUBLIC | RNP_KEY_EXPORT_SUBKEYS));
assert_rnp_success(rnp_key_handle_destroy(key));
assert_rnp_success(rnp_key_handle_destroy(sub));
assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET));
assert_rnp_success(rnp_output_memory_get_buf(keymem, &keybuf, &keylen, false));
assert_rnp_success(rnp_input_from_memory(&input, keybuf, keylen, false));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_output_destroy(keymem));
assert_rnp_success(rnp_locate_key(ffi, "keyid", "22F3A217C0E439CB", &sub));
assert_rnp_success(rnp_key_get_expiration(sub, &expiry));
assert_int_equal(expiry, new_expiry);
assert_rnp_success(rnp_key_handle_destroy(sub));
/* check whether we can change expiration for already expired key */
assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET));
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/alice-sign-sub-pub.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/alice-sign-sub-sec.pgp"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_SECRET_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key));
assert_rnp_success(rnp_locate_key(ffi, "keyid", "22F3A217C0E439CB", &sub));
assert_rnp_success(rnp_key_unlock(key, "password"));
assert_rnp_success(rnp_key_unlock(sub, "password"));
assert_rnp_success(rnp_key_set_expiration(key, 1));
assert_rnp_success(rnp_key_get_expiration(key, &expiry));
assert_int_equal(expiry, 1);
assert_rnp_success(rnp_key_set_expiration(sub, 1));
assert_rnp_success(rnp_key_get_expiration(sub, &expiry));
assert_int_equal(expiry, 1);
assert_rnp_success(rnp_key_set_expiration(key, 0));
assert_rnp_success(rnp_key_get_expiration(key, &expiry));
assert_int_equal(expiry, 0);
assert_rnp_success(rnp_key_set_expiration(sub, 0));
assert_rnp_success(rnp_key_get_expiration(sub, &expiry));
assert_int_equal(expiry, 0);
assert_rnp_success(rnp_key_handle_destroy(key));
assert_rnp_success(rnp_key_handle_destroy(sub));
// TODO: check expiration date in direct-key signature, check without
// self-signature/binding signature.
assert_rnp_success(rnp_ffi_destroy(ffi));
}
TEST_F(rnp_tests, test_ffi_mdc_8k_boundary)
{
rnp_ffi_t ffi = NULL;
rnp_input_t input = NULL;
assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG"));
assert_rnp_success(rnp_ffi_set_pass_provider(ffi, getpasscb, (void *) "password"));
assert_rnp_success(rnp_input_from_path(&input, "data/keyrings/1/pubring.gpg"));
assert_rnp_success(rnp_load_keys(ffi, "GPG", input, RNP_LOAD_SAVE_PUBLIC_KEYS));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_input_from_path(&input, "data/keyrings/1/secring.gpg"));
assert_rnp_success(rnp_load_keys(ffi, "GPG", input, RNP_LOAD_SAVE_SECRET_KEYS));
assert_rnp_success(rnp_input_destroy(input));
/* correctly process two messages */
assert_rnp_success(rnp_input_from_path(&input, "data/test_messages/message_mdc_8k_1.pgp"));
rnp_output_t output = NULL;
assert_rnp_success(rnp_output_to_null(&output));
rnp_op_verify_t verify;
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
/* check signature */
size_t sig_count = 0;
assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sig_count));
assert_int_equal(sig_count, 1);
rnp_op_verify_signature_t sig = NULL;
assert_rnp_success(rnp_op_verify_get_signature_at(verify, 0, &sig));
assert_rnp_success(rnp_op_verify_signature_get_status(sig));
/* cleanup */
assert_rnp_success(rnp_op_verify_destroy(verify));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_input_from_path(&input, "data/test_messages/message_mdc_8k_2.pgp"));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_success(rnp_op_verify_execute(verify));
/* check signature */
sig_count = 0;
assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sig_count));
assert_int_equal(sig_count, 1);
assert_rnp_success(rnp_op_verify_get_signature_at(verify, 0, &sig));
assert_rnp_success(rnp_op_verify_signature_get_status(sig));
/* cleanup */
assert_rnp_success(rnp_op_verify_destroy(verify));
assert_rnp_success(rnp_input_destroy(input));
/* let it gracefully fail on message 1 with the last byte cut */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message_mdc_8k_cut1.pgp"));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_failure(rnp_op_verify_execute(verify));
/* cleanup */
assert_rnp_success(rnp_op_verify_destroy(verify));
assert_rnp_success(rnp_input_destroy(input));
/* let it gracefully fail on message 1 with the last 22 bytes (MDC size) cut */
assert_rnp_success(
rnp_input_from_path(&input, "data/test_messages/message_mdc_8k_cut22.pgp"));
assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
assert_rnp_failure(rnp_op_verify_execute(verify));
/* cleanup */
assert_rnp_success(rnp_op_verify_destroy(verify));
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_output_destroy(output));
assert_rnp_success(rnp_ffi_destroy(ffi));
}

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

@ -915,8 +915,8 @@ TEST_F(rnp_tests, test_generated_key_sigs)
// primary
{
pgp_key_t pub = {0};
pgp_key_t sec = {0};
pgp_key_t pub = {};
pgp_key_t sec = {};
rnp_keygen_primary_desc_t desc;
pgp_fingerprint_t fp = {};
pgp_sig_subpkt_t * subpkt = NULL;
@ -940,6 +940,10 @@ TEST_F(rnp_tests, test_generated_key_sigs)
primary_sec = rnp_key_store_get_key_by_grip(secring, pgp_key_get_grip(&pub));
assert_non_null(primary_pub);
assert_non_null(primary_sec);
assert_true(primary_pub->valid);
assert_true(primary_pub->validated);
assert_true(primary_sec->valid);
assert_true(primary_sec->validated);
// check packet and subsig counts
assert_int_equal(3, pgp_key_get_rawpacket_count(&pub));
@ -1009,34 +1013,48 @@ TEST_F(rnp_tests, test_generated_key_sigs)
// validate via an alternative method
// primary_pub + pubring
assert_rnp_success(pgp_key_validate(primary_pub, pubring));
primary_pub->valid = false;
primary_pub->validated = false;
pgp_key_validate(primary_pub, pubring);
assert_true(primary_pub->valid);
assert_true(primary_pub->validated);
// primary_sec + pubring
assert_rnp_success(pgp_key_validate(primary_sec, pubring));
primary_sec->valid = false;
primary_sec->validated = false;
pgp_key_validate(primary_sec, pubring);
assert_true(primary_sec->valid);
assert_true(primary_sec->validated);
// primary_pub + secring
assert_rnp_success(pgp_key_validate(primary_pub, secring));
primary_pub->valid = primary_pub->validated = false;
pgp_key_validate(primary_pub, secring);
assert_true(primary_pub->valid);
assert_true(primary_pub->validated);
// primary_sec + secring
assert_rnp_success(pgp_key_validate(primary_sec, secring));
primary_sec->valid = primary_sec->validated = false;
pgp_key_validate(primary_sec, secring);
assert_true(primary_sec->valid);
assert_true(primary_sec->validated);
// modify a hashed portion of the sig packet, offset may change in future
pgp_subsig_t *sig = pgp_key_get_subsig(primary_pub, 0);
assert_non_null(sig);
sig->sig.hashed_data[10] ^= 0xff;
sig->validated = false;
// ensure validation fails
assert_rnp_success(pgp_key_validate(primary_pub, pubring));
pgp_key_validate(primary_pub, pubring);
assert_false(primary_pub->valid);
assert_true(primary_pub->validated);
// restore the original data
sig->sig.hashed_data[10] ^= 0xff;
assert_rnp_success(pgp_key_validate(primary_pub, pubring));
sig->validated = false;
pgp_key_validate(primary_pub, pubring);
assert_true(primary_pub->valid);
assert_true(primary_pub->validated);
}
// sub
{
pgp_key_t pub = {0};
pgp_key_t sec = {0};
pgp_key_t pub = {};
pgp_key_t sec = {};
rnp_keygen_subkey_desc_t desc;
pgp_fingerprint_t fp = {};
pgp_sig_subpkt_t * subpkt = NULL;
@ -1051,6 +1069,10 @@ TEST_F(rnp_tests, test_generated_key_sigs)
// generate
assert_true(pgp_generate_subkey(
&desc, true, primary_sec, primary_pub, &sec, &pub, NULL, PGP_KEY_STORE_GPG));
assert_true(pub.valid);
assert_true(pub.validated);
assert_true(sec.valid);
assert_true(sec.validated);
// check packet and subsig counts
assert_int_equal(2, pgp_key_get_rawpacket_count(&pub));
@ -1109,12 +1131,22 @@ TEST_F(rnp_tests, test_generated_key_sigs)
sub_sec = rnp_key_store_get_key_by_grip(secring, pgp_key_get_grip(&pub));
assert_non_null(sub_pub);
assert_non_null(sub_sec);
assert_true(sub_pub->valid);
assert_true(sub_pub->validated);
assert_true(sub_sec->valid);
assert_true(sub_sec->validated);
// validate via an alternative method
assert_rnp_success(pgp_key_validate(sub_pub, pubring));
sub_pub->valid = false;
sub_pub->validated = false;
pgp_key_validate(sub_pub, pubring);
assert_true(sub_pub->valid);
assert_rnp_success(pgp_key_validate(sub_sec, pubring));
assert_true(sub_pub->validated);
sub_sec->valid = false;
sub_sec->validated = false;
pgp_key_validate(sub_sec, pubring);
assert_true(sub_sec->valid);
assert_true(sub_sec->validated);
}
rnp_key_store_free(pubring);

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

@ -0,0 +1,47 @@
/*
* 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"
TEST_F(rnp_tests, test_issue_1115)
{
rnp_ffi_t ffi = NULL;
rnp_input_t input = NULL;
assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG"));
assert_rnp_success(
rnp_input_from_path(&input, "data/test_key_validity/case9/pubring.gpg"));
assert_rnp_success(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL));
assert_rnp_success(rnp_input_destroy(input));
rnp_key_handle_t key = NULL;
assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key));
uint32_t expiry = 0;
assert_rnp_success(rnp_key_get_expiration(key, &expiry));
assert_int_equal(expiry, 0);
assert_rnp_success(rnp_key_handle_destroy(key));
assert_rnp_success(rnp_ffi_destroy(ffi));
}

21
third_party/rnp/src/tests/key-add-userid.cpp поставляемый
Просмотреть файл

@ -68,8 +68,7 @@ TEST_F(rnp_tests, test_key_add_userid)
// add a userid
rnp_selfsig_cert_info_t selfsig;
memset(&selfsig, 0, sizeof(selfsig));
rnp_selfsig_cert_info_t selfsig = {};
strcpy((char *) selfsig.userid, "added1");
selfsig.key_flags = 0xAB;
selfsig.key_expiration = 123456789;
@ -79,17 +78,18 @@ TEST_F(rnp_tests, test_key_add_userid)
// make sure this userid has been marked as primary
assert_int_equal(pgp_key_get_userid_count(key) - 1, key->uid0);
// make sure key expiration and flags are set
assert_int_equal(123456789, pgp_key_get_expiration(key));
assert_int_equal(0xAB, pgp_key_get_flags(key));
// try to add the same userid (should fail)
rnp_selfsig_cert_info_t dup_selfsig;
memset(&dup_selfsig, 0, sizeof(dup_selfsig));
rnp_selfsig_cert_info_t dup_selfsig = {};
strcpy((char *) dup_selfsig.userid, "added1");
assert_false(
pgp_key_add_userid_certified(key, pgp_key_get_pkt(key), PGP_HASH_SHA1, &dup_selfsig));
// try to add another primary userid (should fail)
rnp_selfsig_cert_info_t selfsig2;
memset(&selfsig2, 0, sizeof(selfsig2));
rnp_selfsig_cert_info_t selfsig2 = {};
strcpy((char *) selfsig2.userid, "added2");
selfsig2.primary = 1;
assert_false(
@ -107,12 +107,14 @@ TEST_F(rnp_tests, test_key_add_userid)
assert_int_equal(pgp_key_get_userid_count(key), uidc + 2);
assert_int_equal(pgp_key_get_subsig_count(key), subsigc + 2);
// make sure key expiration and flags are now updated
assert_int_equal(0, pgp_key_get_expiration(key));
assert_int_equal(0xCD, pgp_key_get_flags(key));
// check the userids array
// added1
assert_int_equal(0, strcmp(pgp_key_get_userid(key, uidc)->str, "added1"));
assert_int_equal(uidc, pgp_key_get_subsig(key, subsigc)->uid);
assert_int_equal(0xAB, pgp_key_get_subsig(key, subsigc)->key_flags);
assert_int_equal(123456789, pgp_key_get_expiration(key));
// added2
assert_int_equal(0, strcmp(pgp_key_get_userid(key, uidc + 1)->str, "added2"));
assert_int_equal(uidc + 1, pgp_key_get_subsig(key, subsigc + 1)->uid);
@ -142,12 +144,15 @@ TEST_F(rnp_tests, test_key_add_userid)
assert_int_equal(pgp_key_get_userid_count(key), uidc + 2);
assert_int_equal(pgp_key_get_subsig_count(key), subsigc + 2);
// make sure correct key expiration and flags are set
assert_int_equal(0, pgp_key_get_expiration(key));
assert_int_equal(0xCD, pgp_key_get_flags(key));
// check the userids array
// added1
assert_int_equal(0, strcmp(pgp_key_get_userid(key, uidc)->str, "added1"));
assert_int_equal(uidc, pgp_key_get_subsig(key, subsigc)->uid);
assert_int_equal(0xAB, pgp_key_get_subsig(key, subsigc)->key_flags);
assert_int_equal(123456789, pgp_key_get_expiration(key));
// added2
assert_int_equal(0, strcmp(pgp_key_get_userid(key, uidc + 1)->str, "added2"));
assert_int_equal(uidc + 1, pgp_key_get_subsig(key, subsigc + 1)->uid);

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

@ -75,13 +75,11 @@ TEST_F(rnp_tests, test_key_protect_load_pgp)
pgp_key_t *tmp = NULL;
assert_non_null(tmp = rnp_tests_get_key_by_id(ks, keyids[0], NULL));
assert_non_null(tmp);
// steal this key from the store
key = (pgp_key_t *) calloc(1, sizeof(*key));
key = new pgp_key_t();
assert_non_null(key);
memcpy(key, tmp, sizeof(*key));
assert_true(rnp_key_store_remove_key(ks, tmp));
pgp_key_copy(key, tmp, false);
rnp_key_store_free(ks);
}
@ -250,5 +248,5 @@ TEST_F(rnp_tests, test_key_protect_load_pgp)
assert_true(mpi_equal(&pgp_key_get_material(key)->rsa.u, &u));
// cleanup
pgp_key_free(key);
delete key;
}

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

@ -52,7 +52,7 @@ TEST_F(rnp_tests, test_key_store_search)
// add our fake test keys
for (size_t i = 0; i < ARRAY_SIZE(testdata); i++) {
for (size_t n = 0; n < testdata[i].count; n++) {
pgp_key_t key = {0};
pgp_key_t key = {};
key.pkt.tag = PGP_PKT_PUBLIC_KEY;
key.pkt.version = PGP_V4;

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

@ -142,6 +142,13 @@ key_store_add(rnp_key_store_t *keyring, const char *keypath)
src_close(&keysrc);
}
static bool
key_check(const rnp_key_store_t *keyring, const std::string &keyid, bool valid)
{
pgp_key_t *key = rnp_tests_get_key_by_id(keyring, keyid, NULL);
return key && (key->validated) && (key->valid == valid);
}
TEST_F(rnp_tests, test_forged_key_validate)
{
rnp_key_store_t *pubring;
@ -152,19 +159,14 @@ TEST_F(rnp_tests, test_forged_key_validate)
/* load valid dsa-eg key */
key_store_add(pubring, DATA_PATH "dsa-eg-pub.pgp");
key = rnp_tests_get_key_by_id(pubring, "C8A10A7D78273E10", NULL);
assert_non_null(key);
assert_true(key->valid);
assert_true(key_check(pubring, "C8A10A7D78273E10", true));
rnp_key_store_clear(pubring);
/* load dsa-eg key with forged self-signature. Subkey will not be valid as well. */
/* load dsa-eg key with forged self-signature and binding. Subkey will not be valid as
* well. */
key_store_add(pubring, DATA_PATH "dsa-eg-pub-forged-key.pgp");
key = rnp_tests_get_key_by_id(pubring, "C8A10A7D78273E10", NULL);
assert_non_null(key);
assert_false(key->valid);
key = rnp_tests_get_key_by_id(pubring, "02A5715C3537717E", NULL);
assert_non_null(key);
assert_false(key->valid);
assert_true(key_check(pubring, "C8A10A7D78273E10", false));
assert_true(key_check(pubring, "02A5715C3537717E", false));
rnp_key_store_clear(pubring);
/* load dsa-eg key with forged key material */
@ -178,26 +180,18 @@ TEST_F(rnp_tests, test_forged_key_validate)
/* load dsa-eg keypair with forged subkey binding signature */
key_store_add(pubring, DATA_PATH "dsa-eg-pub-forged-subkey.pgp");
key = rnp_tests_get_key_by_id(pubring, "02A5715C3537717E", NULL);
assert_non_null(key);
assert_false(key->valid);
key = rnp_tests_get_key_by_id(pubring, "C8A10A7D78273E10", NULL);
assert_non_null(key);
assert_true(key->valid);
assert_true(key_check(pubring, "02A5715C3537717E", false));
assert_true(key_check(pubring, "C8A10A7D78273E10", true));
rnp_key_store_clear(pubring);
/* load valid eddsa key */
key_store_add(pubring, DATA_PATH "ecc-25519-pub.pgp");
key = rnp_tests_get_key_by_id(pubring, "CC786278981B0728", NULL);
assert_non_null(key);
assert_true(key->valid);
assert_true(key_check(pubring, "CC786278981B0728", true));
rnp_key_store_clear(pubring);
/* load eddsa key with forged self-signature */
key_store_add(pubring, DATA_PATH "ecc-25519-pub-forged-key.pgp");
key = rnp_tests_get_key_by_id(pubring, "CC786278981B0728", NULL);
assert_non_null(key);
assert_false(key->valid);
assert_true(key_check(pubring, "CC786278981B0728", false));
rnp_key_store_clear(pubring);
/* load eddsa key with forged key material */
@ -209,22 +203,15 @@ TEST_F(rnp_tests, test_forged_key_validate)
/* load valid ecdsa/ecdh p-256 keypair */
key_store_add(pubring, DATA_PATH "ecc-p256-pub.pgp");
key = rnp_tests_get_key_by_id(pubring, "23674F21B2441527", NULL);
assert_non_null(key);
assert_true(key->valid);
key = rnp_tests_get_key_by_id(pubring, "37E285E9E9851491", NULL);
assert_non_null(key);
assert_true(key->valid);
assert_true(key_check(pubring, "23674F21B2441527", true));
assert_true(key_check(pubring, "37E285E9E9851491", true));
rnp_key_store_clear(pubring);
/* load ecdsa/ecdh key with forged self-signature. Subkey is not valid as well. */
/* load ecdsa/ecdh key with forged self-signature. Both valid since there is valid binding.
*/
key_store_add(pubring, DATA_PATH "ecc-p256-pub-forged-key.pgp");
key = rnp_tests_get_key_by_id(pubring, "23674F21B2441527", NULL);
assert_non_null(key);
assert_false(key->valid);
key = rnp_tests_get_key_by_id(pubring, "37E285E9E9851491", NULL);
assert_non_null(key);
assert_false(key->valid);
assert_true(key_check(pubring, "23674F21B2441527", true));
assert_true(key_check(pubring, "37E285E9E9851491", true));
rnp_key_store_clear(pubring);
/* load ecdsa/ecdh key with forged key material. Subkey is not valid as well. */
@ -234,59 +221,43 @@ TEST_F(rnp_tests, test_forged_key_validate)
key = rnp_tests_key_search(pubring, "ecc-p256");
assert_non_null(key);
assert_false(key->valid);
key = rnp_tests_get_key_by_id(pubring, "37E285E9E9851491", NULL);
assert_non_null(key);
assert_false(key->valid);
assert_true(key_check(pubring, "37E285E9E9851491", false));
rnp_key_store_clear(pubring);
/* load ecdsa/ecdh keypair with forged subkey binding signature */
key_store_add(pubring, DATA_PATH "ecc-p256-pub-forged-subkey.pgp");
key = rnp_tests_get_key_by_id(pubring, "37E285E9E9851491", NULL);
assert_non_null(key);
assert_false(key->valid);
key = rnp_tests_get_key_by_id(pubring, "23674F21B2441527", NULL);
assert_non_null(key);
assert_true(key->valid);
assert_true(key_check(pubring, "37E285E9E9851491", false));
assert_true(key_check(pubring, "23674F21B2441527", true));
rnp_key_store_clear(pubring);
/* load ecdsa/ecdh keypair without certification */
/* load ecdsa/ecdh keypair without certification: valid since have binding */
key_store_add(pubring, DATA_PATH "ecc-p256-pub-no-certification.pgp");
key = rnp_tests_get_key_by_id(pubring, "23674F21B2441527", NULL);
assert_non_null(key);
assert_false(key->valid);
key = rnp_tests_get_key_by_id(pubring, "37E285E9E9851491", NULL);
assert_non_null(key);
assert_false(key->valid);
assert_true(key_check(pubring, "23674F21B2441527", true));
assert_true(key_check(pubring, "37E285E9E9851491", true));
rnp_key_store_clear(pubring);
/* load ecdsa/ecdh keypair without certification and invalid binding */
key_store_add(pubring, DATA_PATH "ecc-p256-pub-no-cert-malf-binding.pgp");
assert_true(key_check(pubring, "23674F21B2441527", false));
assert_true(key_check(pubring, "37E285E9E9851491", false));
rnp_key_store_clear(pubring);
/* load ecdsa/ecdh keypair without subkey binding */
key_store_add(pubring, DATA_PATH "ecc-p256-pub-no-binding.pgp");
key = rnp_tests_get_key_by_id(pubring, "23674F21B2441527", NULL);
assert_non_null(key);
assert_true(key->valid);
key = rnp_tests_get_key_by_id(pubring, "37E285E9E9851491", NULL);
assert_non_null(key);
assert_false(key->valid);
assert_true(key_check(pubring, "23674F21B2441527", true));
assert_true(key_check(pubring, "37E285E9E9851491", false));
rnp_key_store_clear(pubring);
/* load valid rsa/rsa keypair */
key_store_add(pubring, DATA_PATH "rsa-rsa-pub.pgp");
key = rnp_tests_get_key_by_id(pubring, "2FB9179118898E8B", NULL);
assert_non_null(key);
assert_true(key->valid);
key = rnp_tests_get_key_by_id(pubring, "6E2F73008F8B8D6E", NULL);
assert_non_null(key);
assert_true(key->valid);
assert_true(key_check(pubring, "2FB9179118898E8B", true));
assert_true(key_check(pubring, "6E2F73008F8B8D6E", true));
rnp_key_store_clear(pubring);
/* load rsa/rsa key with forged self-signature. Subkey is not valid as well. */
/* load rsa/rsa key with forged self-signature. Valid because of valid binding. */
key_store_add(pubring, DATA_PATH "rsa-rsa-pub-forged-key.pgp");
key = rnp_tests_get_key_by_id(pubring, "2FB9179118898E8B", NULL);
assert_non_null(key);
assert_false(key->valid);
key = rnp_tests_get_key_by_id(pubring, "6E2F73008F8B8D6E", NULL);
assert_non_null(key);
assert_false(key->valid);
assert_true(key_check(pubring, "2FB9179118898E8B", true));
assert_true(key_check(pubring, "6E2F73008F8B8D6E", true));
rnp_key_store_clear(pubring);
/* load rsa/rsa key with forged key material. Subkey is not valid as well. */
@ -296,59 +267,45 @@ TEST_F(rnp_tests, test_forged_key_validate)
key = rnp_tests_key_search(pubring, "rsa-rsa");
assert_non_null(key);
assert_false(key->valid);
key = rnp_tests_get_key_by_id(pubring, "6E2F73008F8B8D6E", NULL);
assert_non_null(key);
assert_false(key->valid);
assert_true(key_check(pubring, "6E2F73008F8B8D6E", false));
rnp_key_store_clear(pubring);
/* load rsa/rsa keypair with forged subkey binding signature */
key_store_add(pubring, DATA_PATH "rsa-rsa-pub-forged-subkey.pgp");
key = rnp_tests_get_key_by_id(pubring, "6E2F73008F8B8D6E", NULL);
assert_non_null(key);
assert_false(key->valid);
key = rnp_tests_get_key_by_id(pubring, "2FB9179118898E8B", NULL);
assert_non_null(key);
assert_true(key->valid);
assert_true(key_check(pubring, "2FB9179118898E8B", true));
assert_true(key_check(pubring, "6E2F73008F8B8D6E", false));
rnp_key_store_clear(pubring);
/* load rsa/rsa keypair with future creation date */
key_store_add(pubring, DATA_PATH "rsa-rsa-pub-future-key.pgp");
key = rnp_tests_get_key_by_id(pubring, "3D032D00EE1EC3F5", NULL);
assert_non_null(key);
assert_false(key->valid);
key = rnp_tests_get_key_by_id(pubring, "021085B640CE8DCE", NULL);
assert_non_null(key);
assert_false(key->valid);
assert_true(key_check(pubring, "3D032D00EE1EC3F5", false));
assert_true(key_check(pubring, "021085B640CE8DCE", false));
rnp_key_store_clear(pubring);
/* load eddsa/rsa keypair with certification with future creation date */
/* load eddsa/rsa keypair with certification with future creation date - valid because of
* binding. */
key_store_add(pubring, DATA_PATH "ecc-25519-pub-future-cert.pgp");
key = rnp_tests_get_key_by_id(pubring, "D3B746FA852C2BE8", NULL);
assert_non_null(key);
assert_false(key->valid);
key = rnp_tests_get_key_by_id(pubring, "EB8C21ACDC15CA14", NULL);
assert_non_null(key);
assert_false(key->valid);
assert_true(key_check(pubring, "D3B746FA852C2BE8", true));
assert_true(key_check(pubring, "EB8C21ACDC15CA14", true));
rnp_key_store_clear(pubring);
/* load eddsa/rsa keypair with certification with future creation date - invalid because of
* invalid binding. */
key_store_add(pubring, DATA_PATH "ecc-25519-pub-future-cert-malf-bind.pgp");
assert_true(key_check(pubring, "D3B746FA852C2BE8", false));
assert_true(key_check(pubring, "EB8C21ACDC15CA14", false));
rnp_key_store_clear(pubring);
/* load ecdsa/rsa keypair with expired subkey */
key_store_add(pubring, DATA_PATH "ecc-p256-pub-expired-subkey.pgp");
key = rnp_tests_get_key_by_id(pubring, "23674F21B2441527", NULL);
assert_non_null(key);
assert_true(key->valid);
key = rnp_tests_get_key_by_id(pubring, "37E285E9E9851491", NULL);
assert_non_null(key);
assert_false(key->valid);
assert_true(key_check(pubring, "23674F21B2441527", true));
assert_true(key_check(pubring, "37E285E9E9851491", false));
rnp_key_store_clear(pubring);
/* load ecdsa/ecdh keypair with expired key */
key_store_add(pubring, DATA_PATH "ecc-p256-pub-expired-key.pgp");
key = rnp_tests_get_key_by_id(pubring, "23674F21B2441527", NULL);
assert_non_null(key);
assert_false(key->valid);
key = rnp_tests_get_key_by_id(pubring, "37E285E9E9851491", NULL);
assert_non_null(key);
assert_false(key->valid);
assert_true(key_check(pubring, "23674F21B2441527", false));
assert_true(key_check(pubring, "37E285E9E9851491", false));
rnp_key_store_clear(pubring);
rnp_key_store_free(pubring);
@ -465,4 +422,35 @@ TEST_F(rnp_tests, test_key_validity)
assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0));
assert_false(subkey->valid);
rnp_key_store_free(pubring);
/* Case8:
* Keys Alice [pub, sub]
* Userid is stripped from the key, but it still has valid subkey binding
* Result: Alice [valid], Alice sub[valid]
*/
pubring = rnp_key_store_new(PGP_KEY_STORE_GPG, KEYSIG_PATH "case8/pubring.gpg");
assert_non_null(pubring);
assert_true(rnp_key_store_load_from_path(pubring, NULL));
assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C", NULL));
assert_true(key->valid);
assert_int_equal(pgp_key_get_subkey_count(key), 1);
assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0));
assert_true(subkey->valid);
rnp_key_store_free(pubring);
/* Case9:
* Keys Alice [pub, sub]
* Alice key has two self-signatures, one which expires key and second without key
* expiration.
* Result: Alice [valid], Alice sub[valid]
*/
pubring = rnp_key_store_new(PGP_KEY_STORE_GPG, KEYSIG_PATH "case9/pubring.gpg");
assert_non_null(pubring);
assert_true(rnp_key_store_load_from_path(pubring, NULL));
assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C", NULL));
assert_true(key->valid);
assert_int_equal(pgp_key_get_subkey_count(key), 1);
assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0));
assert_true(subkey->valid);
rnp_key_store_free(pubring);
}

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

@ -58,6 +58,9 @@ TEST_F(rnp_tests, test_load_v3_keyring_pgp)
assert_int_equal(pgp_key_get_flags(key),
PGP_KF_ENCRYPT | PGP_KF_SIGN | PGP_KF_CERTIFY | PGP_KF_AUTH);
// confirm that key expiration is correct
assert_int_equal(pgp_key_get_expiration(key), 0);
// cleanup
rnp_key_store_free(key_store);
@ -84,7 +87,7 @@ TEST_F(rnp_tests, test_load_v3_keyring_pgp)
assert_true(pgp_key_is_locked(key));
// decrypt the key
pgp_rawpacket_t *pkt = pgp_key_get_rawpacket(key, 0);
const pgp_rawpacket_t *pkt = pgp_key_get_rawpacket(key, 0);
pgp_key_pkt_t * seckey =
pgp_decrypt_seckey_pgp(pkt->raw, pkt->length, pgp_key_get_pkt(key), "password");
assert_non_null(seckey);
@ -713,7 +716,7 @@ TEST_F(rnp_tests, test_load_merge)
TEST_F(rnp_tests, test_load_public_from_secret)
{
pgp_key_t * key, *skey1, *skey2, keycp;
pgp_key_t * key, *skey1, *skey2, keycp = {};
uint8_t keyid[PGP_KEY_ID_SIZE];
uint8_t sub1id[PGP_KEY_ID_SIZE];
uint8_t sub2id[PGP_KEY_ID_SIZE];
@ -741,7 +744,6 @@ TEST_F(rnp_tests, test_load_public_from_secret)
memcmp(pgp_key_get_subkey_grip(&keycp, 1), pgp_key_get_grip(skey2), PGP_KEY_GRIP_SIZE));
assert_false(memcmp(pgp_key_get_grip(&keycp), pgp_key_get_grip(key), PGP_KEY_GRIP_SIZE));
assert_int_equal(pgp_key_get_rawpacket(&keycp, 0)->tag, PGP_PKT_SECRET_KEY);
pgp_key_free_data(&keycp);
/* copy the public part */
assert_rnp_success(pgp_key_copy(&keycp, key, true));

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

@ -245,6 +245,8 @@ void test_ffi_key_signatures(void **state);
void test_ffi_keys_import(void **state);
void test_ffi_stripped_keys_import(void **state);
void test_ffi_import_keys_check_pktlen(void **state);
void test_ffi_calculate_iterations(void **state);
@ -279,6 +281,12 @@ void test_ffi_secret_sig_import(void **state);
void test_ffi_rnp_request_password(void **state);
void test_ffi_key_revoke(void **state);
void test_ffi_set_key_expiry(void **state);
void test_ffi_mdc_8k_boundary(void **state);
void test_dsa_roundtrip(void **state);
void test_dsa_verify_negative(void **state);
@ -351,6 +359,8 @@ void test_partial_length_first_packet_length(void **state);
void test_kbx_nsigs(void **state);
void test_issue_1115(void **state);
#define assert_true(a) EXPECT_TRUE((a))
#define assert_false(a) EXPECT_FALSE((a))
#define assert_string_equal(a, b) EXPECT_STREQ((a), (b))

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

@ -1162,7 +1162,7 @@ validate_key_sigs(const char *path)
for (size_t i = 0; i < rnp_key_store_get_key_count(pubring); i++) {
pgp_key_t *pkey = rnp_key_store_get_key(pubring, i);
assert_non_null(pkey);
assert_rnp_success(pgp_key_validate(pkey, pubring));
pgp_key_validate(pkey, pubring);
assert_true(pkey->valid);
}
rnp_key_store_free(pubring);
@ -1179,7 +1179,7 @@ TEST_F(rnp_tests, test_stream_key_signature_validate)
assert_true(rnp_key_store_load_from_path(pubring, NULL));
assert_int_equal(rnp_key_store_get_key_count(pubring), 1);
assert_non_null(pkey = rnp_key_store_get_key(pubring, 0));
assert_rnp_success(pgp_key_validate(pkey, pubring));
pgp_key_validate(pkey, pubring);
assert_true(pkey->valid);
rnp_key_store_free(pubring);
@ -1190,7 +1190,7 @@ TEST_F(rnp_tests, test_stream_key_signature_validate)
assert_true(rnp_key_store_get_key_count(pubring) > 0);
for (size_t i = 0; i < rnp_key_store_get_key_count(pubring); i++) {
pkey = rnp_key_store_get_key(pubring, i);
assert_rnp_success(pgp_key_validate(pkey, pubring));
pgp_key_validate(pkey, pubring);
// subkey #2 is expired
if (i == 2) {
assert_false(pkey->valid);

2
third_party/rnp/src/tests/user-prefs.cpp поставляемый
Просмотреть файл

@ -46,7 +46,7 @@ find_subsig(const pgp_key_t *key, const char *userid)
}
// find the subsig index
for (size_t i = 0; i < pgp_key_get_subsig_count(key); i++) {
pgp_subsig_t *subsig = pgp_key_get_subsig(key, i);
const pgp_subsig_t *subsig = pgp_key_get_subsig(key, i);
if ((int) subsig->uid == uididx) {
return subsig;
}