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:
Marcus Brinkmann 2003-04-27 20:53:04 +00:00
parent e254482818
commit 2971894b27
10 changed files with 715 additions and 166 deletions

12
NEWS
View File

@ -78,6 +78,10 @@ Noteworthy changes in version 0.4.1 (unreleased)
GpgmeImportResult and GpgmeImportStatus objects. Thus, the GpgmeImportResult and GpgmeImportStatus objects. Thus, the
gpgme_op_import_ext variant is deprecated. 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: * Interface changes relative to the 0.4.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GpgmeIOCb CHANGED: Return type from void to GpgmeError. 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 gpgme_op_import_result NEW
GpgmeImportStatus NEW GpgmeImportStatus NEW
GpgmeImportResult 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) Noteworthy changes in version 0.4.0 (2002-12-23)

View File

@ -1,5 +1,10 @@
2003-04-27 Marcus Brinkmann <marcus@g10code.de> 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.texi (Deleting Keys): Document
GPGME_Ambiguous_Specification. GPGME_Ambiguous_Specification.
(Error Values): Remove GPGME_Invalid_Type and GPGME_Invalid_Mode. (Error Values): Remove GPGME_Invalid_Type and GPGME_Invalid_Mode.

View File

@ -73,6 +73,7 @@ This is Edition @value{EDITION}, last updated @value{UPDATED}, of
* Introduction:: How to use this manual. * Introduction:: How to use this manual.
* Preparation:: What you should do before using the library. * Preparation:: What you should do before using the library.
* Protocols and Engines:: Supported crypto protocols. * Protocols and Engines:: Supported crypto protocols.
* Algorithms:: Supported algorithms.
* Error Handling:: Error numbers and their meanings. * Error Handling:: Error numbers and their meanings.
* Exchanging Data:: Passing data to and from @acronym{GPGME}. * Exchanging Data:: Passing data to and from @acronym{GPGME}.
* Contexts:: Handling @acronym{GPGME} contexts. * Contexts:: Handling @acronym{GPGME} contexts.
@ -114,6 +115,11 @@ Protocols and Engines
* OpenPGP:: Support for the OpenPGP protocol. * OpenPGP:: Support for the OpenPGP protocol.
* Cryptographic Message Syntax:: Support for the CMS. * 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 Handling
* Error Values:: A list of all error values used. * 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}. 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 @node Error Handling
@chapter Error Handling @chapter Error Handling
@cindex 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, The format of @var{keydata} can be @var{ASCII} armored, for example,
but the details are specific to the crypto engine. 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 The function returns @code{GPGME_No_Error} if the import was completed
successfully, @code{GPGME_Invalid_Value} if @var{keydata} if @var{ctx} 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 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 @table @code
@item GpgmeImportStatus next @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 @item char *fpr
This is the fingerprint of the key that was considered. 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. @code{GpgmeTrustItem} object and releases all associated resources.
@end deftypefun @end deftypefun
@node Crypto Operations @node Crypto Operations
@section Crypto Operations @section Crypto Operations
@cindex cryptographic operation @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 @menu
* Decrypt:: Decrypting a ciphertext. * Decrypt:: Decrypting a ciphertext.
* Verify:: Verifying a signature. * 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 @acronym{ASCII} armor and text mode attributes set for the context
@var{ctx} and the requested signature mode @var{mode}. @var{ctx} and the requested signature mode @var{mode}.
More information about the signatures is available with After the operation completed successfully, the result can be
@code{gpgme_get_op_info}. @xref{Detailed Results}. retrieved with @code{gpgme_op_sign_result}.
If an S/MIME signed message is created using the CMS crypto engine, 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 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. @var{plain} or @var{sig} is not a valid pointer.
@end deftypefun @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 @node Encrypt
@subsection Encrypt @subsection Encrypt

View File

@ -1,5 +1,36 @@
2003-04-27 Marcus Brinkmann <marcus@g10code.de> 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 * delete.c: Include <errno.h> and "gpgme.h", but not "util.h" or
"key.h". "key.h".
(enum delete_problem): Move into function delete_status_handler. (enum delete_problem): Move into function delete_status_handler.

View File

@ -51,6 +51,10 @@ _gpgme_op_encrypt_sign_start (GpgmeCtx ctx, int synchronous,
if (err) if (err)
return err; return err;
err = _gpgme_op_sign_init_result (ctx);
if (err)
return err;
if (!plain) if (!plain)
return GPGME_No_Data; return GPGME_No_Data;
if (!cipher) if (!cipher)

View File

@ -521,3 +521,82 @@ gpgme_get_io_cbs (GpgmeCtx ctx, struct GpgmeIOCbs *io_cbs)
if (ctx && io_cbs) if (ctx && io_cbs)
*io_cbs = 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;
}
}

View File

@ -138,6 +138,41 @@ typedef enum
} }
GpgmeDataEncoding; 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. */ /* The possible signature stati. */
typedef enum 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 gpgme_get_progress_cb (GpgmeCtx ctx, GpgmeProgressCb *cb,
void **hook_value); 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. */ /* Delete all signers from CTX. */
void gpgme_signers_clear (GpgmeCtx 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. */ attribute appears more than once in the key. */
int gpgme_trust_item_get_int_attr (GpgmeTrustItem item, GpgmeAttr what, int gpgme_trust_item_get_int_attr (GpgmeTrustItem item, GpgmeAttr what,
const void *reserved, int idx); 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 /* Encrypt plaintext PLAIN within CTX for the recipients RECP and
store the resulting ciphertext in CIPHER. */ store the resulting ciphertext in CIPHER. */
GpgmeError gpgme_op_encrypt_start (GpgmeCtx ctx, 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, GpgmeError gpgme_op_decrypt_verify (GpgmeCtx ctx,
GpgmeData cipher, GpgmeData plain); 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, GpgmeError gpgme_op_sign_start (GpgmeCtx ctx,
GpgmeData plain, GpgmeData sig, GpgmeData plain, GpgmeData sig,
GpgmeSigMode mode); GpgmeSigMode mode);
@ -756,6 +833,7 @@ GpgmeError gpgme_op_sign (GpgmeCtx ctx,
GpgmeData plain, GpgmeData sig, GpgmeData plain, GpgmeData sig,
GpgmeSigMode mode); GpgmeSigMode mode);
/* Verify within CTX that SIG is a valid signature for TEXT. */ /* Verify within CTX that SIG is a valid signature for TEXT. */
GpgmeError gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig, GpgmeError gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig,
GpgmeData signed_text, GpgmeData plaintext); GpgmeData signed_text, GpgmeData plaintext);

View File

@ -21,6 +21,8 @@
#include <config.h> #include <config.h>
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
#include <string.h>
#include "gpgme.h" #include "gpgme.h"
#include "context.h" #include "context.h"
@ -105,3 +107,79 @@ _gpgme_op_reset (GpgmeCtx ctx, int type)
_gpgme_engine_set_io_cbs (ctx->engine, &io_cbs); _gpgme_engine_set_io_cbs (ctx->engine, &io_cbs);
return err; 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;
}

View File

@ -57,12 +57,22 @@ GpgmeError _gpgme_data_outbound_handler (void *opaque, int fd);
GpgmeError _gpgme_key_new ( GpgmeKey *r_key ); GpgmeError _gpgme_key_new ( GpgmeKey *r_key );
GpgmeError _gpgme_key_new_secret ( 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, GpgmeError _gpgme_op_data_lookup (GpgmeCtx ctx, ctx_op_data_type type,
void **hook, int size, void **hook, int size,
void (*cleanup) (void *)); void (*cleanup) (void *));
/* Prepare a new operation on CTX. */
GpgmeError _gpgme_op_reset (GpgmeCtx ctx, int synchronous); 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 --*/ /*-- verify.c --*/
GpgmeError _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, GpgmeError _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
char *args); char *args);
@ -74,10 +84,18 @@ GpgmeError _gpgme_decrypt_start (GpgmeCtx ctx, int synchronous,
GpgmeData ciph, GpgmeData plain, GpgmeData ciph, GpgmeData plain,
void *status_handler); 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); char *args);
/*-- encrypt.c --*/ /*-- encrypt.c --*/
GpgmeError _gpgme_encrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, GpgmeError _gpgme_encrypt_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
char *args); char *args);

View File

@ -1,4 +1,4 @@
/* sign.c - signing functions /* sign.c - Signing function.
Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003 g10 Code GmbH Copyright (C) 2001, 2002, 2003 g10 Code GmbH
@ -21,157 +21,203 @@
#if HAVE_CONFIG_H #if HAVE_CONFIG_H
#include <config.h> #include <config.h>
#endif #endif
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <errno.h>
#include "util.h" #include "gpgme.h"
#include "context.h" #include "context.h"
#include "ops.h" #include "ops.h"
#define SKIP_TOKEN_OR_RETURN(a) do { \
while (*(a) && *(a) != ' ') (a)++; \ typedef struct
while (*(a) == ' ') (a)++; \
if (!*(a)) \
return; /* oops */ \
} while (0)
struct sign_result
{ {
int okay; struct _gpgme_op_sign_result result;
GpgmeData xmlinfo;
}; /* A pointer to the next pointer of the last invalid signer in
typedef struct sign_result *SignResult; 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 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;
} }
/* Parse the args and save the information while (sig)
<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)
{ {
GpgmeData dh; GpgmeNewSignature next = sig->next;
char helpbuf[100]; free (sig->fpr);
int i; free (sig);
char *s; sig = next;
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)
GpgmeSignResult
gpgme_op_sign_result (GpgmeCtx ctx)
{ {
/* Just close the XML containter. */ op_data_t opd;
_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;
GpgmeError err; 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) if (err)
return err; return err;
switch (code) switch (code)
{ {
case GPGME_STATUS_EOF: case GPGME_STATUS_SIG_CREATED:
err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, (void **) &result, err = parse_sig_created (args, opd->last_sig_p);
-1, NULL); if (err)
if (!err) return err;
{
if (result && result->okay) opd->last_sig_p = &(*opd->last_sig_p)->next;
{
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;
}
break; break;
case GPGME_STATUS_SIG_CREATED: case GPGME_STATUS_INV_RECP:
/* FIXME: We have no error return for multiple signatures. */ err = _gpgme_parse_inv_userid (args, opd->last_signer_p);
err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, (void **) &result, if (err)
sizeof (*result), release_sign_result); return err;
append_xml_siginfo (&result->xmlinfo, args);
result->okay = 1; opd->last_signer_p = &(*opd->last_signer_p)->next;
break;
case GPGME_STATUS_EOF:
if (opd->result.invalid_signers)
return GPGME_Invalid_UserID;
break; break;
default: default:
@ -180,9 +226,25 @@ _gpgme_sign_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
return err; 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 static GpgmeError
_gpgme_op_sign_start (GpgmeCtx ctx, int synchronous, sign_start (GpgmeCtx ctx, int synchronous, GpgmeData plain, GpgmeData sig,
GpgmeData plain, GpgmeData sig,
GpgmeSigMode mode) GpgmeSigMode mode)
{ {
GpgmeError err; GpgmeError err;
@ -191,6 +253,10 @@ _gpgme_op_sign_start (GpgmeCtx ctx, int synchronous,
if (err) if (err)
return 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 if (mode != GPGME_SIG_MODE_NORMAL && mode != GPGME_SIG_MODE_DETACH
&& mode != GPGME_SIG_MODE_CLEAR) && mode != GPGME_SIG_MODE_CLEAR)
return GPGME_Invalid_Value; return GPGME_Invalid_Value;
@ -217,38 +283,21 @@ _gpgme_op_sign_start (GpgmeCtx ctx, int synchronous,
ctx /* FIXME */); ctx /* FIXME */);
} }
/* Sign the plaintext PLAIN and store the signature in SIG. */
GpgmeError GpgmeError
gpgme_op_sign_start (GpgmeCtx ctx, GpgmeData in, GpgmeData out, gpgme_op_sign_start (GpgmeCtx ctx, GpgmeData plain, GpgmeData sig,
GpgmeSigMode mode) GpgmeSigMode mode)
{ {
return _gpgme_op_sign_start (ctx, 0, in, out, mode); return sign_start (ctx, 0, plain, sig, mode);
} }
/**
* gpgme_op_sign: /* Sign the plaintext PLAIN and store the signature in SIG. */
* @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.
**/
GpgmeError 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) if (!err)
err = _gpgme_wait_one (ctx); err = _gpgme_wait_one (ctx);
return err; return err;