doc/
2003-04-27 Marcus Brinkmann <marcus@g10code.de> * gpgme.texi (Creating a Signature): Add info about GpgmeNewSignature, GpgmeSignResult and gpgme_op_sign_result. (Crypto Operations): Add GpgmeInvalidUserID. (Algorithms): New chapter. gpgme/ 2003-04-27 Marcus Brinkmann <marcus@g10code.de> * gpgme.h (GpgmePubKeyAlgo, GpgmeHashAlgo, GpgmeInvalidUserID, GpgmeNewSignature, GpgmeSignResult): New data types. (gpgme_op_sign_result, gpgme_pubkey_algo_name, gpgme_hash_algo_name): New prototypes. * gpgme.c (gpgme_pubkey_algo_name): New function. (gpgme_hash_algo_name): Likewise. * ops.h (_gpgme_parse_inv_userid, _gpgme_op_sign_init_result): New prototype. (_gpgme_op_sign_status_handler): Fix prototype. * op-support.c: Include <errno.h> and <string.h>. (_gpgme_parse_inv_userid): New function. * sign.c: Include <errno.h> and "gpgme.h", but not <stdio.h>, <assert.h> and "util.h". (SKIP_TOKEN_OR_RETURN): Remove macro. (struct sign_result): Change to op_data_t type and rework it. (release_sign_result): Rename to ... (release_op_data): ... this and rewrite it. (append_xml_info): Remove function. (gpgme_op_sign_result): New function. (parse_sig_created): New function. (_gpgme_sign_status_handler): Change first argument to void *. Rewrite the function to use the new result structure and functions. (_gpgme_op_sign_init_result): New function. (_gpgme_op_sign_start): Rename to ... (sign_start): ... this. Call _gpgme_op_sign_init_result. (gpgme_op_sign_start): Use sign_start instead _gpgme_op_sign_start. (gpgme_op_sign): Likewise.
This commit is contained in:
parent
e254482818
commit
2971894b27
12
NEWS
12
NEWS
@ -78,6 +78,10 @@ Noteworthy changes in version 0.4.1 (unreleased)
|
||||
GpgmeImportResult and GpgmeImportStatus objects. Thus, the
|
||||
gpgme_op_import_ext variant is deprecated.
|
||||
|
||||
* The new gpgme_op_sign_result function provides detailed information
|
||||
about the result of a signing operation in GpgmeSignResult,
|
||||
GpgmeInvalidUserID and GpgmeNewSignature objects.
|
||||
|
||||
* Interface changes relative to the 0.4.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
GpgmeIOCb CHANGED: Return type from void to GpgmeError.
|
||||
@ -108,6 +112,14 @@ gpgme_op_import_ext DEPRECATED: Use gpgme_op_import_result.
|
||||
gpgme_op_import_result NEW
|
||||
GpgmeImportStatus NEW
|
||||
GpgmeImportResult NEW
|
||||
GpgmePubKeyAlgo NEW
|
||||
GpgmeHashAlgo NEW
|
||||
GpgmeInvalidUserID NEW
|
||||
GpgmeNewSignature NEW
|
||||
GpgmeSignResult NEW
|
||||
gpgme_op_sign_result NEW
|
||||
gpgme_pubkey_algo_name NEW
|
||||
gpgme_hash_algo_name NEW
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Noteworthy changes in version 0.4.0 (2002-12-23)
|
||||
|
@ -1,5 +1,10 @@
|
||||
2003-04-27 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* gpgme.texi (Creating a Signature): Add info about
|
||||
GpgmeNewSignature, GpgmeSignResult and gpgme_op_sign_result.
|
||||
(Crypto Operations): Add GpgmeInvalidUserID.
|
||||
(Algorithms): New chapter.
|
||||
|
||||
* gpgme.texi (Deleting Keys): Document
|
||||
GPGME_Ambiguous_Specification.
|
||||
(Error Values): Remove GPGME_Invalid_Type and GPGME_Invalid_Mode.
|
||||
|
201
doc/gpgme.texi
201
doc/gpgme.texi
@ -73,6 +73,7 @@ This is Edition @value{EDITION}, last updated @value{UPDATED}, of
|
||||
* Introduction:: How to use this manual.
|
||||
* Preparation:: What you should do before using the library.
|
||||
* Protocols and Engines:: Supported crypto protocols.
|
||||
* Algorithms:: Supported algorithms.
|
||||
* Error Handling:: Error numbers and their meanings.
|
||||
* Exchanging Data:: Passing data to and from @acronym{GPGME}.
|
||||
* Contexts:: Handling @acronym{GPGME} contexts.
|
||||
@ -114,6 +115,11 @@ Protocols and Engines
|
||||
* OpenPGP:: Support for the OpenPGP protocol.
|
||||
* Cryptographic Message Syntax:: Support for the CMS.
|
||||
|
||||
Algorithms
|
||||
|
||||
* Public Key Algorithms:: A list of all public key algorithms.
|
||||
* Hash Algorithms:: A list of all hash algorithms.
|
||||
|
||||
Error Handling
|
||||
|
||||
* Error Values:: A list of all error values used.
|
||||
@ -728,6 +734,110 @@ GnuPG.
|
||||
The @acronym{CMS} protocol is specified by @code{GPGME_PROTOCOL_CMS}.
|
||||
|
||||
|
||||
@node Algorithms
|
||||
@chapter Algorithms
|
||||
@cindex algorithms
|
||||
|
||||
The crypto backends support a variety of algorithms used in public key
|
||||
cryptography. The following sections list the identifiers used to
|
||||
denote such an algorithm.
|
||||
|
||||
@menu
|
||||
* Public Key Algorithms:: A list of all public key algorithms.
|
||||
* Hash Algorithms:: A list of all hash algorithms.
|
||||
@end menu
|
||||
|
||||
|
||||
@node Public Key Algorithms
|
||||
@section Public Key Algorithms
|
||||
@cindex algorithms, public key
|
||||
@cindex public key algorithms
|
||||
|
||||
Public key algorithms are used for encryption, decryption, signing and
|
||||
verification of signatures.
|
||||
|
||||
@deftp {Data type} {enum GpgmePubKeyAlgo}
|
||||
@tindex GpgmePubKeyAlgo
|
||||
The @code{GpgmePubKeyAlgo} type specifies the set of all public key
|
||||
algorithms that are supported by @acronym{GPGME}. Possible values
|
||||
are:
|
||||
|
||||
@table @code
|
||||
@item GPGME_PK_RSA
|
||||
This value indicates the RSA (Rivest, Shamir, Adleman) algorithm.
|
||||
|
||||
@item GPGME_PK_RSA_E
|
||||
Deprecated. This value indicates the RSA (Rivest, Shamir, Adleman)
|
||||
algorithm for encryption and decryption only.
|
||||
|
||||
@item GPGME_PK_RSA_S
|
||||
Deprecated. This value indicates the RSA (Rivest, Shamir, Adleman)
|
||||
algorithm for signing and verification only.
|
||||
|
||||
@item GPGME_PK_DSA
|
||||
This value indicates DSA, the Digital Signature Algorithm.
|
||||
|
||||
@item GPGME_PK_ELG
|
||||
This value indicates ElGamal.
|
||||
|
||||
@item GPGME_PK_ELG_E
|
||||
This value also indicates ElGamal and is used specifically in GnuPG.
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
@deftypefun {const char *} gpgme_pubkey_algo_name (@w{GpgmePubKeyAlgo @var{algo}})
|
||||
The function @code{gpgme_pubkey_algo_name} returns a pointer to a
|
||||
statically allocated string containing a description of the public key
|
||||
algorithm @var{algo}. This string can be used to output the name of
|
||||
the public key algorithm to the user.
|
||||
|
||||
If @var{algo} is not a valid public key algorithm, @code{NULL} is
|
||||
returned.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@node Hash Algorithms
|
||||
@section Hash Algorithms
|
||||
@cindex algorithms, hash
|
||||
@cindex algorithms, message digest
|
||||
@cindex hash algorithms
|
||||
@cindex message digest algorithms
|
||||
|
||||
Hash (message digest) algorithms are used to compress a long message
|
||||
to make it suitable for public key cryptography.
|
||||
|
||||
@deftp {Data type} {enum GpgmeHashAlgo}
|
||||
@tindex GpgmeHashAlgo
|
||||
The @code{GpgmeHashAlgo} type specifies the set of all hash algorithms
|
||||
that are supported by @acronym{GPGME}. Possible values are:
|
||||
|
||||
@table @code
|
||||
@item GPGME_MD_MD5
|
||||
@item GPGME_MD_SHA1
|
||||
@item GPGME_MD_RMD160
|
||||
@item GPGME_MD_MD2
|
||||
@item GPGME_MD_TIGER
|
||||
@item GPGME_MD_HAVAL
|
||||
@item GPGME_MD_SHA256
|
||||
@item GPGME_MD_SHA384
|
||||
@item GPGME_MD_SHA512
|
||||
@item GPGME_MD_MD4
|
||||
@item GPGME_MD_CRC32
|
||||
@item GPGME_MD_CRC32_RFC1510
|
||||
@item GPGME_MD_CRC24_RFC2440
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
@deftypefun {const char *} gpgme_hash_algo_name (@w{GpgmeHashAlgo @var{algo}})
|
||||
The function @code{gpgme_hash_algo_name} returns a pointer to a
|
||||
statically allocated string containing a description of the hash
|
||||
algorithm @var{algo}. This string can be used to output the name of
|
||||
the hash algorithm to the user.
|
||||
|
||||
If @var{algo} is not a valid hash algorithm, @code{NULL} is returned.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@node Error Handling
|
||||
@chapter Error Handling
|
||||
@cindex error handling
|
||||
@ -2308,6 +2418,9 @@ The function @code{gpgme_op_import} adds the keys in the data buffer
|
||||
The format of @var{keydata} can be @var{ASCII} armored, for example,
|
||||
but the details are specific to the crypto engine.
|
||||
|
||||
After the operation completed successfully, the result can be
|
||||
retrieved with @code{gpgme_op_import_result}.
|
||||
|
||||
The function returns @code{GPGME_No_Error} if the import was completed
|
||||
successfully, @code{GPGME_Invalid_Value} if @var{keydata} if @var{ctx}
|
||||
or @var{keydata} is not a valid pointer, and @code{GPGME_No_Data} if
|
||||
@ -2333,7 +2446,8 @@ import. The structure contains the following members:
|
||||
|
||||
@table @code
|
||||
@item GpgmeImportStatus next
|
||||
This is a pointer to the next status object in the list.
|
||||
This is a pointer to the next status structure in the linked list, or
|
||||
@code{NULL} if this is the last element.
|
||||
|
||||
@item char *fpr
|
||||
This is the fingerprint of the key that was considered.
|
||||
@ -2592,10 +2706,34 @@ The function @code{gpgme_trust_item_release} destroys a
|
||||
@code{GpgmeTrustItem} object and releases all associated resources.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@node Crypto Operations
|
||||
@section Crypto Operations
|
||||
@cindex cryptographic operation
|
||||
|
||||
Sometimes, the result of a crypto operation returns a list of invalid
|
||||
user IDs encountered in processing the request. The following
|
||||
structure is used to hold information about such an user ID.
|
||||
|
||||
@deftp {Data type} {GpgmeInvalidUserID}
|
||||
This is a pointer to a structure used to store a part of the result of
|
||||
a crypto operation which takes user IDs as one input parameter. The
|
||||
structure contains the following members:
|
||||
|
||||
@table @code
|
||||
@item GpgmeInvalidUserID next
|
||||
This is a pointer to the next invalid user ID structure in the linked
|
||||
list, or @code{NULL} if this is the last element.
|
||||
|
||||
@item char *id
|
||||
The invalid user ID encountered.
|
||||
|
||||
@item GpgmeError reason
|
||||
An error code describing the reason why the user ID was found invalid.
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
|
||||
@menu
|
||||
* Decrypt:: Decrypting a ciphertext.
|
||||
* Verify:: Verifying a signature.
|
||||
@ -2994,8 +3132,8 @@ the data object @var{plain} and returns it in the data object
|
||||
@acronym{ASCII} armor and text mode attributes set for the context
|
||||
@var{ctx} and the requested signature mode @var{mode}.
|
||||
|
||||
More information about the signatures is available with
|
||||
@code{gpgme_get_op_info}. @xref{Detailed Results}.
|
||||
After the operation completed successfully, the result can be
|
||||
retrieved with @code{gpgme_op_sign_result}.
|
||||
|
||||
If an S/MIME signed message is created using the CMS crypto engine,
|
||||
the number of certificates to include in the message can be specified
|
||||
@ -3020,6 +3158,63 @@ started successfully, and @code{GPGME_Invalid_Value} if @var{ctx},
|
||||
@var{plain} or @var{sig} is not a valid pointer.
|
||||
@end deftypefun
|
||||
|
||||
@deftp {Data type} {GpgmeNewSignature}
|
||||
This is a pointer to a structure used to store a part of the result of
|
||||
a @code{gpgme_op_sign} operation. The structure contains the
|
||||
following members:
|
||||
|
||||
@table @code
|
||||
@item GpgmeNewSignature next
|
||||
This is a pointer to the next new signature structure in the linked
|
||||
list, or @code{NULL} if this is the last element.
|
||||
|
||||
@item GpgmeSigMode type
|
||||
The type of this signature.
|
||||
|
||||
@item GpgmePubKeyAlgo
|
||||
The public key algorithm used to create this signature.
|
||||
|
||||
@item GpgmeHashAlgo
|
||||
The hash algorithm used to create this signature.
|
||||
|
||||
@item unsigned long class
|
||||
The signature class of this signature.
|
||||
|
||||
@item long int created
|
||||
The creation timestamp of this signature.
|
||||
|
||||
@item char *fpr
|
||||
The fingerprint of the key which was used to create this signature.
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
@deftp {Data type} {GpgmeSignResult}
|
||||
This is a pointer to a structure used to store the result of a
|
||||
@code{gpgme_op_sign} operation. After successfully generating a
|
||||
signature, you can retrieve the pointer to the result with
|
||||
@code{gpgme_op_sign_result}. The structure contains the following
|
||||
members:
|
||||
|
||||
@table @code
|
||||
@item GpgmeInvalidUserID invalid_signers
|
||||
A linked list with information about all invalid user IDs for which a
|
||||
signature could not be created.
|
||||
|
||||
@item GpgmeNewSignature signatures
|
||||
A linked list with information about all signatures created.
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
@deftypefun GpgmeSignResult gpgme_op_sign_result (@w{GpgmeCtx @var{ctx}})
|
||||
The function @code{gpgme_op_sign_result} returns a
|
||||
@code{GpgmeSignResult} pointer to a structure holding the result of a
|
||||
@code{gpgme_op_sign} operation. The pointer is only valid if the last
|
||||
operation on the context was a @code{gpgme_op_sign} or
|
||||
@code{gpgme_op_sign_start} operation, and if this operation finished
|
||||
successfully. The returned pointer is only valid until the next
|
||||
operation is started on the context.
|
||||
@end deftypefun
|
||||
|
||||
|
||||
@node Encrypt
|
||||
@subsection Encrypt
|
||||
|
@ -1,5 +1,36 @@
|
||||
2003-04-27 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* gpgme.h (GpgmePubKeyAlgo, GpgmeHashAlgo, GpgmeInvalidUserID,
|
||||
GpgmeNewSignature, GpgmeSignResult): New data types.
|
||||
(gpgme_op_sign_result, gpgme_pubkey_algo_name,
|
||||
gpgme_hash_algo_name): New prototypes.
|
||||
* gpgme.c (gpgme_pubkey_algo_name): New function.
|
||||
(gpgme_hash_algo_name): Likewise.
|
||||
* ops.h (_gpgme_parse_inv_userid, _gpgme_op_sign_init_result): New
|
||||
prototype.
|
||||
(_gpgme_op_sign_status_handler): Fix prototype.
|
||||
* op-support.c: Include <errno.h> and <string.h>.
|
||||
(_gpgme_parse_inv_userid): New function.
|
||||
* sign.c: Include <errno.h> and "gpgme.h", but not <stdio.h>,
|
||||
<assert.h> and "util.h".
|
||||
(SKIP_TOKEN_OR_RETURN): Remove macro.
|
||||
(struct sign_result): Change to op_data_t type and rework it.
|
||||
(release_sign_result): Rename to ...
|
||||
(release_op_data): ... this and rewrite it.
|
||||
(append_xml_info): Remove function.
|
||||
(gpgme_op_sign_result): New function.
|
||||
(parse_sig_created): New function.
|
||||
(_gpgme_sign_status_handler): Change first argument to void *.
|
||||
Rewrite the function to use the new result structure and functions.
|
||||
(_gpgme_op_sign_init_result): New function.
|
||||
(_gpgme_op_sign_start): Rename to ...
|
||||
(sign_start): ... this. Call _gpgme_op_sign_init_result.
|
||||
(gpgme_op_sign_start): Use sign_start instead _gpgme_op_sign_start.
|
||||
(gpgme_op_sign): Likewise.
|
||||
|
||||
* encrypt-sign.c (_gpgme_op_encrypt_sign_start): Call
|
||||
_gpgme_op_sign_init_result.
|
||||
|
||||
* delete.c: Include <errno.h> and "gpgme.h", but not "util.h" or
|
||||
"key.h".
|
||||
(enum delete_problem): Move into function delete_status_handler.
|
||||
|
@ -51,6 +51,10 @@ _gpgme_op_encrypt_sign_start (GpgmeCtx ctx, int synchronous,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = _gpgme_op_sign_init_result (ctx);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!plain)
|
||||
return GPGME_No_Data;
|
||||
if (!cipher)
|
||||
|
@ -521,3 +521,82 @@ gpgme_get_io_cbs (GpgmeCtx ctx, struct GpgmeIOCbs *io_cbs)
|
||||
if (ctx && io_cbs)
|
||||
*io_cbs = ctx->io_cbs;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
gpgme_pubkey_algo_name (GpgmePubKeyAlgo algo)
|
||||
{
|
||||
switch (algo)
|
||||
{
|
||||
case GPGME_PK_RSA:
|
||||
return "RSA";
|
||||
|
||||
case GPGME_PK_RSA_E:
|
||||
return "RSA-E";
|
||||
|
||||
case GPGME_PK_RSA_S:
|
||||
return "RSA-S";
|
||||
|
||||
case GPGME_PK_ELG_E:
|
||||
return "ELG-E";
|
||||
|
||||
case GPGME_PK_DSA:
|
||||
return "DSA";
|
||||
|
||||
case GPGME_PK_ELG:
|
||||
return "ELG";
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
gpgme_hash_algo_name (GpgmeHashAlgo algo)
|
||||
{
|
||||
switch (algo)
|
||||
{
|
||||
case GPGME_MD_MD5:
|
||||
return "MD5";
|
||||
|
||||
case GPGME_MD_SHA1:
|
||||
return "SHA1";
|
||||
|
||||
case GPGME_MD_RMD160:
|
||||
return "RMD160";
|
||||
|
||||
case GPGME_MD_MD2:
|
||||
return "MD2";
|
||||
|
||||
case GPGME_MD_TIGER:
|
||||
return "TIGER";
|
||||
|
||||
case GPGME_MD_HAVAL:
|
||||
return "HAVAL";
|
||||
|
||||
case GPGME_MD_SHA256:
|
||||
return "SHA256";
|
||||
|
||||
case GPGME_MD_SHA384:
|
||||
return "SHA384";
|
||||
|
||||
case GPGME_MD_SHA512:
|
||||
return "SHA512";
|
||||
|
||||
case GPGME_MD_MD4:
|
||||
return "MD4";
|
||||
|
||||
case GPGME_MD_CRC32:
|
||||
return "CRC32";
|
||||
|
||||
case GPGME_MD_CRC32_RFC1510:
|
||||
return "CRC32-RFC1510";
|
||||
|
||||
case GPGME_MD_CRC24_RFC2440:
|
||||
return "CRC24-RFC2440";
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +138,41 @@ typedef enum
|
||||
}
|
||||
GpgmeDataEncoding;
|
||||
|
||||
|
||||
/* Public key algorithms from libgcrypt. */
|
||||
typedef enum
|
||||
{
|
||||
GPGME_PK_RSA = 1,
|
||||
GPGME_PK_RSA_E = 2,
|
||||
GPGME_PK_RSA_S = 3,
|
||||
GPGME_PK_ELG_E = 16,
|
||||
GPGME_PK_DSA = 17,
|
||||
GPGME_PK_ELG = 20
|
||||
}
|
||||
GpgmePubKeyAlgo;
|
||||
|
||||
|
||||
/* Hash algorithms from libgcrypt. */
|
||||
typedef enum
|
||||
{
|
||||
GPGME_MD_NONE = 0,
|
||||
GPGME_MD_MD5 = 1,
|
||||
GPGME_MD_SHA1 = 2,
|
||||
GPGME_MD_RMD160 = 3,
|
||||
GPGME_MD_MD2 = 5,
|
||||
GPGME_MD_TIGER = 6, /* TIGER/192. */
|
||||
GPGME_MD_HAVAL = 7, /* HAVAL, 5 pass, 160 bit. */
|
||||
GPGME_MD_SHA256 = 8,
|
||||
GPGME_MD_SHA384 = 9,
|
||||
GPGME_MD_SHA512 = 10,
|
||||
GPGME_MD_MD4 = 301,
|
||||
GPGME_MD_CRC32 = 302,
|
||||
GPGME_MD_CRC32_RFC1510 = 303,
|
||||
GPGME_MD_CRC24_RFC2440 = 304
|
||||
}
|
||||
GpgmeHashAlgo;
|
||||
|
||||
|
||||
/* The possible signature stati. */
|
||||
typedef enum
|
||||
{
|
||||
@ -426,6 +461,16 @@ void gpgme_set_progress_cb (GpgmeCtx c, GpgmeProgressCb cb, void *hook_value);
|
||||
void gpgme_get_progress_cb (GpgmeCtx ctx, GpgmeProgressCb *cb,
|
||||
void **hook_value);
|
||||
|
||||
|
||||
/* Return a statically allocated string with the name of the public
|
||||
key algorithm ALGO, or NULL if that name is not known. */
|
||||
const char *gpgme_pubkey_algo_name (GpgmePubKeyAlgo algo);
|
||||
|
||||
/* Return a statically allocated string with the name of the hash
|
||||
algorithm ALGO, or NULL if that name is not known. */
|
||||
const char *gpgme_hash_algo_name (GpgmeHashAlgo algo);
|
||||
|
||||
|
||||
/* Delete all signers from CTX. */
|
||||
void gpgme_signers_clear (GpgmeCtx ctx);
|
||||
|
||||
@ -710,10 +755,18 @@ const char *gpgme_trust_item_get_string_attr (GpgmeTrustItem item,
|
||||
attribute appears more than once in the key. */
|
||||
int gpgme_trust_item_get_int_attr (GpgmeTrustItem item, GpgmeAttr what,
|
||||
const void *reserved, int idx);
|
||||
|
||||
/* Crypto Operations. */
|
||||
|
||||
struct _gpgme_invalid_user_id
|
||||
{
|
||||
struct _gpgme_invalid_user_id *next;
|
||||
char *id;
|
||||
GpgmeError reason;
|
||||
};
|
||||
typedef struct _gpgme_invalid_user_id *GpgmeInvalidUserID;
|
||||
|
||||
/* Crypto operation function. */
|
||||
|
||||
|
||||
/* Encrypt plaintext PLAIN within CTX for the recipients RECP and
|
||||
store the resulting ciphertext in CIPHER. */
|
||||
GpgmeError gpgme_op_encrypt_start (GpgmeCtx ctx,
|
||||
@ -747,8 +800,32 @@ GpgmeError gpgme_op_decrypt_verify_start (GpgmeCtx ctx,
|
||||
GpgmeError gpgme_op_decrypt_verify (GpgmeCtx ctx,
|
||||
GpgmeData cipher, GpgmeData plain);
|
||||
|
||||
/* Sign the plaintext PLAIN and store the signature in SIG. Only
|
||||
detached signatures are supported for now. */
|
||||
|
||||
/* Signing. */
|
||||
struct _gpgme_new_signature
|
||||
{
|
||||
struct _gpgme_new_signature *next;
|
||||
GpgmeSigMode type;
|
||||
GpgmePubKeyAlgo pubkey_algo;
|
||||
GpgmeHashAlgo hash_algo;
|
||||
unsigned long class;
|
||||
long int created;
|
||||
char *fpr;
|
||||
};
|
||||
typedef struct _gpgme_new_signature *GpgmeNewSignature;
|
||||
|
||||
struct _gpgme_op_sign_result
|
||||
{
|
||||
/* The list of invalid signers. */
|
||||
GpgmeInvalidUserID invalid_signers;
|
||||
GpgmeNewSignature signatures;
|
||||
};
|
||||
typedef struct _gpgme_op_sign_result *GpgmeSignResult;
|
||||
|
||||
/* Retrieve a pointer to the result of the signing operation. */
|
||||
GpgmeSignResult gpgme_op_sign_result (GpgmeCtx ctx);
|
||||
|
||||
/* Sign the plaintext PLAIN and store the signature in SIG. */
|
||||
GpgmeError gpgme_op_sign_start (GpgmeCtx ctx,
|
||||
GpgmeData plain, GpgmeData sig,
|
||||
GpgmeSigMode mode);
|
||||
@ -756,6 +833,7 @@ GpgmeError gpgme_op_sign (GpgmeCtx ctx,
|
||||
GpgmeData plain, GpgmeData sig,
|
||||
GpgmeSigMode mode);
|
||||
|
||||
|
||||
/* Verify within CTX that SIG is a valid signature for TEXT. */
|
||||
GpgmeError gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig,
|
||||
GpgmeData signed_text, GpgmeData plaintext);
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gpgme.h"
|
||||
#include "context.h"
|
||||
@ -105,3 +107,79 @@ _gpgme_op_reset (GpgmeCtx ctx, int type)
|
||||
_gpgme_engine_set_io_cbs (ctx->engine, &io_cbs);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
GpgmeError
|
||||
_gpgme_parse_inv_userid (char *args, GpgmeInvalidUserID *userid)
|
||||
{
|
||||
GpgmeInvalidUserID inv_userid;
|
||||
char *tail;
|
||||
long int reason;
|
||||
|
||||
inv_userid = malloc (sizeof (*inv_userid));
|
||||
if (!inv_userid)
|
||||
return GPGME_Out_Of_Core;
|
||||
inv_userid->next = NULL;
|
||||
errno = 0;
|
||||
reason = strtol (args, &tail, 0);
|
||||
if (errno || args == tail || *tail != ' ')
|
||||
{
|
||||
/* The crypto backend does not behave. */
|
||||
free (inv_userid);
|
||||
return GPGME_General_Error;
|
||||
}
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
inv_userid->reason = GPGME_Unknown_Reason;
|
||||
|
||||
case 1:
|
||||
inv_userid->reason = GPGME_Not_Found;
|
||||
|
||||
case 2:
|
||||
inv_userid->reason = GPGME_Ambiguous_Specification;
|
||||
|
||||
case 3:
|
||||
inv_userid->reason = GPGME_Wrong_Key_Usage;
|
||||
|
||||
case 4:
|
||||
inv_userid->reason = GPGME_Key_Revoked;
|
||||
|
||||
case 5:
|
||||
inv_userid->reason = GPGME_Key_Expired;
|
||||
|
||||
case 6:
|
||||
inv_userid->reason = GPGME_No_CRL_Known;
|
||||
|
||||
case 7:
|
||||
inv_userid->reason = GPGME_CRL_Too_Old;
|
||||
|
||||
case 8:
|
||||
inv_userid->reason = GPGME_Policy_Mismatch;
|
||||
|
||||
case 9:
|
||||
inv_userid->reason = GPGME_No_Secret_Key;
|
||||
|
||||
case 10:
|
||||
inv_userid->reason = GPGME_Key_Not_Trusted;
|
||||
}
|
||||
|
||||
while (*tail == ' ')
|
||||
tail++;
|
||||
if (*tail)
|
||||
{
|
||||
inv_userid->id = strdup (tail);
|
||||
if (!inv_userid->id)
|
||||
{
|
||||
free (inv_userid);
|
||||
return GPGME_Out_Of_Core;
|
||||
}
|
||||
}
|
||||
else
|
||||
inv_userid->id = NULL;
|
||||
|
||||
*userid = inv_userid;
|
||||
return 0;
|
||||
}
|
||||
|
24
gpgme/ops.h
24
gpgme/ops.h
@ -57,12 +57,22 @@ GpgmeError _gpgme_data_outbound_handler (void *opaque, int fd);
|
||||
GpgmeError _gpgme_key_new ( GpgmeKey *r_key );
|
||||
GpgmeError _gpgme_key_new_secret ( GpgmeKey *r_key );
|
||||
|
||||
/*-- op-support.c --*/
|
||||
|
||||
/* From op-support.c. */
|
||||
|
||||
/* Find or create the op data object of type TYPE. */
|
||||
GpgmeError _gpgme_op_data_lookup (GpgmeCtx ctx, ctx_op_data_type type,
|
||||
void **hook, int size,
|
||||
void (*cleanup) (void *));
|
||||
|
||||
/* Prepare a new operation on CTX. */
|
||||
GpgmeError _gpgme_op_reset (GpgmeCtx ctx, int synchronous);
|
||||
|
||||
/* Parse the invalid user ID status line in ARGS and return the result
|
||||
in USERID. */
|
||||
GpgmeError _gpgme_parse_inv_userid (char *args, GpgmeInvalidUserID *userid);
|
||||
|
||||
|
||||
/*-- verify.c --*/
|
||||
GpgmeError _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
|
||||
char *args);
|
||||
@ -74,10 +84,18 @@ GpgmeError _gpgme_decrypt_start (GpgmeCtx ctx, int synchronous,
|
||||
GpgmeData ciph, GpgmeData plain,
|
||||
void *status_handler);
|
||||
|
||||
/*-- sign.c --*/
|
||||
GpgmeError _gpgme_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
|
||||
|
||||
/* From sign.c. */
|
||||
|
||||
/* Create an initial op data object for signing. Needs to be called
|
||||
once before calling _gpgme_sign_status_handler. */
|
||||
GpgmeError _gpgme_op_sign_init_result (GpgmeCtx ctx);
|
||||
|
||||
/* Process a status line for signing operations. */
|
||||
GpgmeError _gpgme_sign_status_handler (void *priv, GpgmeStatusCode code,
|
||||
char *args);
|
||||
|
||||
|
||||
/*-- encrypt.c --*/
|
||||
GpgmeError _gpgme_encrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
|
||||
char *args);
|
||||
|
359
gpgme/sign.c
359
gpgme/sign.c
@ -1,4 +1,4 @@
|
||||
/* sign.c - signing functions
|
||||
/* sign.c - Signing function.
|
||||
Copyright (C) 2000 Werner Koch (dd9jn)
|
||||
Copyright (C) 2001, 2002, 2003 g10 Code GmbH
|
||||
|
||||
@ -21,157 +21,203 @@
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "gpgme.h"
|
||||
#include "context.h"
|
||||
#include "ops.h"
|
||||
|
||||
#define SKIP_TOKEN_OR_RETURN(a) do { \
|
||||
while (*(a) && *(a) != ' ') (a)++; \
|
||||
while (*(a) == ' ') (a)++; \
|
||||
if (!*(a)) \
|
||||
return; /* oops */ \
|
||||
} while (0)
|
||||
|
||||
struct sign_result
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int okay;
|
||||
GpgmeData xmlinfo;
|
||||
};
|
||||
typedef struct sign_result *SignResult;
|
||||
struct _gpgme_op_sign_result result;
|
||||
|
||||
/* A pointer to the next pointer of the last invalid signer in
|
||||
the list. This makes appending new invalid signers painless
|
||||
while preserving the order. */
|
||||
GpgmeInvalidUserID *last_signer_p;
|
||||
|
||||
/* Likewise for signature information. */
|
||||
GpgmeNewSignature *last_sig_p;
|
||||
} *op_data_t;
|
||||
|
||||
|
||||
static void
|
||||
release_sign_result (void *hook)
|
||||
release_op_data (void *hook)
|
||||
{
|
||||
SignResult result = (SignResult) hook;
|
||||
op_data_t opd = (op_data_t) hook;
|
||||
GpgmeInvalidUserID invalid_signer = opd->result.invalid_signers;
|
||||
GpgmeNewSignature sig = opd->result.signatures;
|
||||
|
||||
gpgme_data_release (result->xmlinfo);
|
||||
while (invalid_signer)
|
||||
{
|
||||
GpgmeInvalidUserID next = invalid_signer->next;
|
||||
free (invalid_signer->id);
|
||||
free (invalid_signer);
|
||||
invalid_signer = next;
|
||||
}
|
||||
|
||||
while (sig)
|
||||
{
|
||||
GpgmeNewSignature next = sig->next;
|
||||
free (sig->fpr);
|
||||
free (sig);
|
||||
sig = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the args and save the information
|
||||
<type> <pubkey algo> <hash algo> <class> <timestamp> <key fpr>
|
||||
in an XML structure. With args of NULL the xml structure is
|
||||
closed. */
|
||||
static void
|
||||
append_xml_siginfo (GpgmeData *rdh, char *args)
|
||||
|
||||
GpgmeSignResult
|
||||
gpgme_op_sign_result (GpgmeCtx ctx)
|
||||
{
|
||||
GpgmeData dh;
|
||||
char helpbuf[100];
|
||||
int i;
|
||||
char *s;
|
||||
unsigned long ul;
|
||||
|
||||
if (!*rdh)
|
||||
{
|
||||
if (gpgme_data_new (rdh))
|
||||
{
|
||||
return; /* fixme: We are ignoring out-of-core */
|
||||
}
|
||||
dh = *rdh;
|
||||
_gpgme_data_append_string (dh, "<GnupgOperationInfo>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
dh = *rdh;
|
||||
_gpgme_data_append_string (dh, " </signature>\n");
|
||||
}
|
||||
|
||||
if (!args)
|
||||
{
|
||||
/* Just close the XML containter. */
|
||||
_gpgme_data_append_string (dh, "</GnupgOperationInfo>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
_gpgme_data_append_string (dh, " <signature>\n");
|
||||
|
||||
_gpgme_data_append_string (dh,
|
||||
*args == 'D' ? " <detached/>\n" :
|
||||
*args == 'C' ? " <cleartext/>\n" :
|
||||
*args == 'S' ? " <standard/>\n" : "");
|
||||
SKIP_TOKEN_OR_RETURN (args);
|
||||
|
||||
sprintf (helpbuf, " <algo>%d</algo>\n", atoi (args));
|
||||
_gpgme_data_append_string (dh, helpbuf);
|
||||
SKIP_TOKEN_OR_RETURN (args);
|
||||
|
||||
i = atoi (args);
|
||||
sprintf (helpbuf, " <hashalgo>%d</hashalgo>\n", atoi (args));
|
||||
_gpgme_data_append_string (dh, helpbuf);
|
||||
switch (i)
|
||||
{
|
||||
case 1: s = "pgp-md5"; break;
|
||||
case 2: s = "pgp-sha1"; break;
|
||||
case 3: s = "pgp-ripemd160"; break;
|
||||
case 5: s = "pgp-md2"; break;
|
||||
case 6: s = "pgp-tiger192"; break;
|
||||
case 7: s = "pgp-haval-5-160"; break;
|
||||
case 8: s = "pgp-sha256"; break;
|
||||
case 9: s = "pgp-sha384"; break;
|
||||
case 10: s = "pgp-sha512"; break;
|
||||
default: s = "pgp-unknown"; break;
|
||||
}
|
||||
sprintf (helpbuf, " <micalg>%s</micalg>\n", s);
|
||||
_gpgme_data_append_string (dh,helpbuf);
|
||||
SKIP_TOKEN_OR_RETURN (args);
|
||||
|
||||
sprintf (helpbuf, " <sigclass>%.2s</sigclass>\n", args);
|
||||
_gpgme_data_append_string (dh, helpbuf);
|
||||
SKIP_TOKEN_OR_RETURN (args);
|
||||
|
||||
ul = strtoul (args, NULL, 10);
|
||||
sprintf (helpbuf, " <created>%lu</created>\n", ul);
|
||||
_gpgme_data_append_string (dh, helpbuf);
|
||||
SKIP_TOKEN_OR_RETURN (args);
|
||||
|
||||
/* Count the length of the finperprint. */
|
||||
for (i = 0; args[i] && args[i] != ' '; i++)
|
||||
;
|
||||
_gpgme_data_append_string (dh, " <fpr>");
|
||||
_gpgme_data_append (dh, args, i);
|
||||
_gpgme_data_append_string (dh, "</fpr>\n");
|
||||
}
|
||||
|
||||
GpgmeError
|
||||
_gpgme_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
|
||||
{
|
||||
SignResult result;
|
||||
op_data_t opd;
|
||||
GpgmeError err;
|
||||
|
||||
err = _gpgme_passphrase_status_handler (ctx, code, args);
|
||||
err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, (void **) &opd, -1, NULL);
|
||||
if (err || !opd)
|
||||
return NULL;
|
||||
|
||||
return &opd->result;
|
||||
}
|
||||
|
||||
|
||||
static GpgmeError
|
||||
parse_sig_created (char *args, GpgmeNewSignature *sigp)
|
||||
{
|
||||
GpgmeNewSignature sig;
|
||||
char *tail;
|
||||
|
||||
sig = malloc (sizeof (*sig));
|
||||
if (!sig)
|
||||
return GPGME_Out_Of_Core;
|
||||
|
||||
sig->next = NULL;
|
||||
switch (*args)
|
||||
{
|
||||
case 'S':
|
||||
sig->type = GPGME_SIG_MODE_NORMAL;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
sig->type = GPGME_SIG_MODE_DETACH;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
sig->type = GPGME_SIG_MODE_CLEAR;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* The backend engine is not behaving. */
|
||||
free (sig);
|
||||
return GPGME_General_Error;
|
||||
}
|
||||
|
||||
args++;
|
||||
if (*args != ' ')
|
||||
{
|
||||
free (sig);
|
||||
return GPGME_General_Error;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
sig->pubkey_algo = strtol (args, &tail, 0);
|
||||
if (errno || args == tail || *tail != ' ')
|
||||
{
|
||||
/* The crypto backend does not behave. */
|
||||
free (sig);
|
||||
return GPGME_General_Error;
|
||||
}
|
||||
args = tail;
|
||||
|
||||
sig->hash_algo = strtol (args, &tail, 0);
|
||||
if (errno || args == tail || *tail != ' ')
|
||||
{
|
||||
/* The crypto backend does not behave. */
|
||||
free (sig);
|
||||
return GPGME_General_Error;
|
||||
}
|
||||
args = tail;
|
||||
|
||||
sig->class = strtol (args, &tail, 0);
|
||||
if (errno || args == tail || *tail != ' ')
|
||||
{
|
||||
/* The crypto backend does not behave. */
|
||||
free (sig);
|
||||
return GPGME_General_Error;
|
||||
}
|
||||
args = tail;
|
||||
|
||||
sig->created = strtol (args, &tail, 0);
|
||||
if (errno || args == tail || *tail != ' ')
|
||||
{
|
||||
/* The crypto backend does not behave. */
|
||||
free (sig);
|
||||
return GPGME_General_Error;
|
||||
}
|
||||
args = tail;
|
||||
while (*args == ' ')
|
||||
args++;
|
||||
|
||||
if (!*args)
|
||||
{
|
||||
/* The crypto backend does not behave. */
|
||||
free (sig);
|
||||
return GPGME_General_Error;
|
||||
}
|
||||
|
||||
tail = strchr (args, ' ');
|
||||
if (tail)
|
||||
*tail = '\0';
|
||||
|
||||
sig->fpr = strdup (args);
|
||||
if (!sig->fpr)
|
||||
{
|
||||
free (sig);
|
||||
return GPGME_Out_Of_Core;
|
||||
}
|
||||
*sigp = sig;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
GpgmeError
|
||||
_gpgme_sign_status_handler (void *priv, GpgmeStatusCode code, char *args)
|
||||
{
|
||||
GpgmeCtx ctx = (GpgmeCtx) priv;
|
||||
GpgmeError err;
|
||||
op_data_t opd;
|
||||
|
||||
err = _gpgme_passphrase_status_handler (priv, code, args);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, (void **) &opd, -1, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case GPGME_STATUS_EOF:
|
||||
err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, (void **) &result,
|
||||
-1, NULL);
|
||||
if (!err)
|
||||
{
|
||||
if (result && result->okay)
|
||||
{
|
||||
append_xml_siginfo (&result->xmlinfo, NULL);
|
||||
_gpgme_set_op_info (ctx, result->xmlinfo);
|
||||
result->xmlinfo = NULL;
|
||||
}
|
||||
else if (!result || !result->okay)
|
||||
/* FIXME: choose a better error code? */
|
||||
err = GPGME_No_Data;
|
||||
}
|
||||
case GPGME_STATUS_SIG_CREATED:
|
||||
err = parse_sig_created (args, opd->last_sig_p);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
opd->last_sig_p = &(*opd->last_sig_p)->next;
|
||||
break;
|
||||
|
||||
case GPGME_STATUS_SIG_CREATED:
|
||||
/* FIXME: We have no error return for multiple signatures. */
|
||||
err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, (void **) &result,
|
||||
sizeof (*result), release_sign_result);
|
||||
append_xml_siginfo (&result->xmlinfo, args);
|
||||
result->okay = 1;
|
||||
case GPGME_STATUS_INV_RECP:
|
||||
err = _gpgme_parse_inv_userid (args, opd->last_signer_p);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
opd->last_signer_p = &(*opd->last_signer_p)->next;
|
||||
break;
|
||||
|
||||
case GPGME_STATUS_EOF:
|
||||
if (opd->result.invalid_signers)
|
||||
return GPGME_Invalid_UserID;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -180,9 +226,25 @@ _gpgme_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
GpgmeError
|
||||
_gpgme_op_sign_init_result (GpgmeCtx ctx)
|
||||
{
|
||||
GpgmeError err;
|
||||
op_data_t opd;
|
||||
|
||||
err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, (void **) &opd,
|
||||
sizeof (*opd), release_op_data);
|
||||
if (err)
|
||||
return err;
|
||||
opd->last_signer_p = &opd->result.invalid_signers;
|
||||
opd->last_sig_p = &opd->result.signatures;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static GpgmeError
|
||||
_gpgme_op_sign_start (GpgmeCtx ctx, int synchronous,
|
||||
GpgmeData plain, GpgmeData sig,
|
||||
sign_start (GpgmeCtx ctx, int synchronous, GpgmeData plain, GpgmeData sig,
|
||||
GpgmeSigMode mode)
|
||||
{
|
||||
GpgmeError err;
|
||||
@ -191,6 +253,10 @@ _gpgme_op_sign_start (GpgmeCtx ctx, int synchronous,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = _gpgme_op_sign_init_result (ctx);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (mode != GPGME_SIG_MODE_NORMAL && mode != GPGME_SIG_MODE_DETACH
|
||||
&& mode != GPGME_SIG_MODE_CLEAR)
|
||||
return GPGME_Invalid_Value;
|
||||
@ -217,38 +283,21 @@ _gpgme_op_sign_start (GpgmeCtx ctx, int synchronous,
|
||||
ctx /* FIXME */);
|
||||
}
|
||||
|
||||
|
||||
/* Sign the plaintext PLAIN and store the signature in SIG. */
|
||||
GpgmeError
|
||||
gpgme_op_sign_start (GpgmeCtx ctx, GpgmeData in, GpgmeData out,
|
||||
gpgme_op_sign_start (GpgmeCtx ctx, GpgmeData plain, GpgmeData sig,
|
||||
GpgmeSigMode mode)
|
||||
{
|
||||
return _gpgme_op_sign_start (ctx, 0, in, out, mode);
|
||||
return sign_start (ctx, 0, plain, sig, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* gpgme_op_sign:
|
||||
* @ctx: The context
|
||||
* @in: Data to be signed
|
||||
* @out: Detached signature
|
||||
* @mode: Signature creation mode
|
||||
*
|
||||
* Create a detached signature for @in and write it to @out.
|
||||
* The data will be signed using either the default key or the ones
|
||||
* defined through @ctx.
|
||||
* The defined modes for signature create are:
|
||||
* <literal>
|
||||
* GPGME_SIG_MODE_NORMAL (or 0)
|
||||
* GPGME_SIG_MODE_DETACH
|
||||
* GPGME_SIG_MODE_CLEAR
|
||||
* </literal>
|
||||
* Note that the settings done by gpgme_set_armor() and gpgme_set_textmode()
|
||||
* are ignore for @mode GPGME_SIG_MODE_CLEAR.
|
||||
*
|
||||
* Return value: 0 on success or an error code.
|
||||
**/
|
||||
|
||||
/* Sign the plaintext PLAIN and store the signature in SIG. */
|
||||
GpgmeError
|
||||
gpgme_op_sign (GpgmeCtx ctx, GpgmeData in, GpgmeData out, GpgmeSigMode mode)
|
||||
gpgme_op_sign (GpgmeCtx ctx, GpgmeData plain, GpgmeData sig, GpgmeSigMode mode)
|
||||
{
|
||||
GpgmeError err = _gpgme_op_sign_start (ctx, 1, in, out, mode);
|
||||
GpgmeError err = sign_start (ctx, 1, plain, sig, mode);
|
||||
if (!err)
|
||||
err = _gpgme_wait_one (ctx);
|
||||
return err;
|
||||
|
Loading…
Reference in New Issue
Block a user