Skip to content

Commit

Permalink
FFI: Add functions rnp_key_signature_create/rnp_signature_set_revoker…
Browse files Browse the repository at this point in the history
…/rnp_key_signature_sign.
  • Loading branch information
ni4 committed Dec 22, 2023
1 parent fc51357 commit 56bce87
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 0 deletions.
44 changes: 44 additions & 0 deletions include/rnp/rnp.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ typedef uint32_t rnp_result_t;
#define RNP_VERIFY_REQUIRE_ALL_SIGS (1U << 1)
#define RNP_VERIFY_ALLOW_HIDDEN_RECIPIENT (1U << 2)

/**
* Revocation key flags.
*/
#define RNP_REVOKER_SENSITIVE (1U << 0)

/**
* Return a constant string describing the result code
*/
Expand Down Expand Up @@ -1519,6 +1524,45 @@ RNP_API rnp_result_t rnp_key_get_signature_at(rnp_key_handle_t key,
size_t idx,
rnp_signature_handle_t *sig);

/**
* @brief Create new blank signature, issued by signer. It may be customized via the
* rnp_signature_set_* calls, and finalized via the rnp_signature_sign() call.
*
* @param signer signing key, must be secret, and must exist in the keyring up to the
* rnp_signature_sign() call. Cannot be NULL.
* @param sigtype type of the signature. See rnp_signature_get_type() for possible values.
* @param sig on success signature handle will be stored here. It is initialized with current
* creation time, default hash algorithm and version.
* @return RNP_SUCCESS or error code if failued.
*/
RNP_API rnp_result_t rnp_key_signature_create(rnp_key_handle_t signer,
const char * sigtype,
rnp_signature_handle_t *sig);

/**
* @brief Add designated revoker subpacket to the signature. See RFC 4880, section 5.2.3.15.
* Only single revoker could be set - subsequent calls would overwrite the previous one.
*
* @param sig editable key signature handle, i.e. created with rnp_key_signature_create().
* @param revoker revoker's key.
* @param flags additional flags. The following flag is currently supported:
* RNP_REVOKER_SENSITIVE: information about the revocation key should be
* considered as sensitive. See RFC for the details.
* @return RNP_SUCCESS or error code if failued.
*/
RNP_API rnp_result_t rnp_key_signature_set_revoker(rnp_signature_handle_t sig,
rnp_key_handle_t revoker,
uint32_t flags);

/**
* @brief Finalize populating and sign signature, created with rnp_key_signature_create, and
* add it to the corresponding key.
*
* @param sig signature handle.
* @return RNP_SUCCESS or error code if failed.
*/
RNP_API rnp_result_t rnp_key_signature_sign(rnp_signature_handle_t sig);

/**
* @brief Get number of the designated revokers for the key. Designated revoker is a key, which
* is allowed to revoke this key.
Expand Down
1 change: 1 addition & 0 deletions src/lib/ffi-priv-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct rnp_signature_handle_st {
const pgp_key_t *key;
pgp_subsig_t * sig;
bool own_sig;
bool new_sig;
};

struct rnp_recipient_handle_st {
Expand Down
129 changes: 129 additions & 0 deletions src/lib/rnp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6174,6 +6174,135 @@ try {
}
FFI_GUARD

static bool
is_key_signature_supported(int stype)

Check warning on line 6178 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6178

Added line #L6178 was not covered by tests
{
/* We support creation of only direct-key signature for now */
switch (stype) {
case PGP_SIG_DIRECT:
return true;
default:
return false;

Check warning on line 6185 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6181-L6185

Added lines #L6181 - L6185 were not covered by tests
}

Check notice

Code scanning / CodeQL

No trivial switch statements Note

This switch statement should either handle more cases, or be rewritten as an if statement.
}

rnp_result_t
rnp_key_signature_create(rnp_key_handle_t signer,

Check warning on line 6190 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6190

Added line #L6190 was not covered by tests
const char * sigtype,
rnp_signature_handle_t *sig)
try {
if (!signer || !sigtype || !sig) {
return RNP_ERROR_NULL_POINTER;

Check warning on line 6195 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6194-L6195

Added lines #L6194 - L6195 were not covered by tests
}
auto stype = id_str_pair::lookup(sig_type_map, sigtype);
if (!is_key_signature_supported(stype)) {
FFI_LOG(signer->ffi, "Not yet supported sigtype: %s", sigtype);
return RNP_ERROR_BAD_PARAMETERS;

Check warning on line 6200 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6197-L6200

Added lines #L6197 - L6200 were not covered by tests
}

pgp_key_t *sigkey = get_key_require_secret(signer);
if (!sigkey) {
return RNP_ERROR_BAD_PARAMETERS;

Check warning on line 6205 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6203-L6205

Added lines #L6203 - L6205 were not covered by tests
}
*sig = (rnp_signature_handle_t) calloc(1, sizeof(**sig));
if (!*sig) {
return RNP_ERROR_OUT_OF_MEMORY;

Check warning on line 6209 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6207-L6209

Added lines #L6207 - L6209 were not covered by tests
}
try {
pgp_signature_t sigpkt;
sigkey->sign_init(signer->ffi->rng(),

Check warning on line 6213 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6212-L6213

Added lines #L6212 - L6213 were not covered by tests
sigpkt,
DEFAULT_PGP_HASH_ALG,
signer->ffi->context.time(),

Check warning on line 6216 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6216

Added line #L6216 was not covered by tests
sigkey->version());
sigpkt.set_type(static_cast<pgp_sig_type_t>(stype));
(*sig)->sig = new pgp_subsig_t(sigpkt);
(*sig)->ffi = signer->ffi;
(*sig)->key = sigkey;
(*sig)->own_sig = true;
(*sig)->new_sig = true;
} catch (const std::exception &e) {
FFI_LOG(signer->ffi, "%s", e.what());
free(*sig);
*sig = NULL;
return RNP_ERROR_OUT_OF_MEMORY;

Check warning on line 6228 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6218-L6228

Added lines #L6218 - L6228 were not covered by tests
}

return RNP_SUCCESS;

Check warning on line 6231 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6231

Added line #L6231 was not covered by tests
}
FFI_GUARD

Check warning on line 6233 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6233

Added line #L6233 was not covered by tests

rnp_result_t
rnp_key_signature_set_revoker(rnp_signature_handle_t sig,

Check warning on line 6236 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6236

Added line #L6236 was not covered by tests
rnp_key_handle_t revoker,
uint32_t flags)
try {
if (!sig || !revoker) {
return RNP_ERROR_NULL_POINTER;

Check warning on line 6241 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6240-L6241

Added lines #L6240 - L6241 were not covered by tests
}
if (!sig->new_sig) {
return RNP_ERROR_BAD_PARAMETERS;

Check warning on line 6244 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6243-L6244

Added lines #L6243 - L6244 were not covered by tests
}
bool sensitive = extract_flag(flags, RNP_REVOKER_SENSITIVE);
if (flags) {
FFI_LOG(sig->ffi, "Unsupported flags: %" PRIu32, flags);
return RNP_ERROR_BAD_PARAMETERS;

Check warning on line 6249 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6246-L6249

Added lines #L6246 - L6249 were not covered by tests
}
auto key = get_key_prefer_public(revoker);
if (!key) {
return RNP_ERROR_BAD_PARAMETERS;

Check warning on line 6253 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6251-L6253

Added lines #L6251 - L6253 were not covered by tests
}
sig->sig->sig.set_revoker(key->pkt(), sensitive);
return RNP_SUCCESS;

Check warning on line 6256 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6255-L6256

Added lines #L6255 - L6256 were not covered by tests
}
FFI_GUARD

Check warning on line 6258 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6258

Added line #L6258 was not covered by tests

rnp_result_t
rnp_key_signature_sign(rnp_signature_handle_t sig)

Check warning on line 6261 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6261

Added line #L6261 was not covered by tests
try {
if (!sig) {
return RNP_ERROR_NULL_POINTER;

Check warning on line 6264 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6263-L6264

Added lines #L6263 - L6264 were not covered by tests
}
if (!sig->new_sig) {
return RNP_ERROR_BAD_PARAMETERS;

Check warning on line 6267 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6266-L6267

Added lines #L6266 - L6267 were not covered by tests
}
auto &sigpkt = sig->sig->sig;
if (!is_key_signature_supported(sigpkt.type())) {
return RNP_ERROR_BAD_STATE;

Check warning on line 6271 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6269-L6271

Added lines #L6269 - L6271 were not covered by tests
}
/* Locate signer */
auto signer = sig->ffi->secring->get_signer(sigpkt);
if (!signer) {
return RNP_ERROR_BAD_STATE;

Check warning on line 6276 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6274-L6276

Added lines #L6274 - L6276 were not covered by tests
}
/* Unlock if needed */
rnp::KeyLocker seclock(*signer);
if (signer->is_locked() && !signer->unlock(sig->ffi->pass_provider)) {
FFI_LOG(sig->ffi, "Failed to unlock secret key");
return RNP_ERROR_BAD_PASSWORD;

Check warning on line 6282 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6279-L6282

Added lines #L6279 - L6282 were not covered by tests
}
/* Sign */
switch (sigpkt.type()) {
case PGP_SIG_DIRECT:
signer->sign_direct(signer->pkt(), sigpkt, sig->ffi->context);
break;
default:
FFI_LOG(sig->ffi, "Not yet supported signature type.");
return RNP_ERROR_BAD_STATE;

Check warning on line 6291 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6285-L6291

Added lines #L6285 - L6291 were not covered by tests
}

Check notice

Code scanning / CodeQL

No trivial switch statements Note

This switch statement should either handle more cases, or be rewritten as an if statement.
/* Add to the keyring(s) */
signer->add_sig(sigpkt, PGP_UID_NONE, true);
signer->refresh_data(sig->ffi->context);
auto sigpub = sig->ffi->pubring->get_signer(sigpkt);
if (sigpub) {
sigpub->add_sig(sigpkt, PGP_UID_NONE, true);
sigpub->refresh_data(sig->ffi->context);

Check warning on line 6299 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6294-L6299

Added lines #L6294 - L6299 were not covered by tests
}

return RNP_SUCCESS;

Check warning on line 6302 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6302

Added line #L6302 was not covered by tests
}
FFI_GUARD

Check warning on line 6304 in src/lib/rnp.cpp

View check run for this annotation

Codecov / codecov/patch

src/lib/rnp.cpp#L6304

Added line #L6304 was not covered by tests

rnp_result_t
rnp_key_get_revoker_count(rnp_key_handle_t handle, size_t *count)
try {
Expand Down

0 comments on commit 56bce87

Please sign in to comment.