First cut at GPG encrytion support (decryption and doc update are pending).

git-svn-id: file:///home/mbr/svn/fwknop/trunk@39 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
Damien Stuart 2009-01-25 03:58:50 +00:00
parent 04674071ef
commit e846cdd44d
22 changed files with 726 additions and 144 deletions

View File

@ -3,11 +3,12 @@ dnl Process thie file with autoconf to produce teh configure script
AC_PREREQ(2.53) AC_PREREQ(2.53)
m4_define(my_package, [fwknop]) m4_define(my_package, [fwknop])
m4_define(my_version, [2.0.0-alpha]) m4_define(my_version, [1.10.0-alpha])
m4_define(my_bug_email, [dstuart@dstuart.org]) m4_define(my_bug_email, [dstuart@dstuart.org])
AC_INIT(my_package, my_version, my_bug_email) AC_INIT(my_package, my_version, my_bug_email)
AC_CONFIG_AUX_DIR(config) AC_CONFIG_AUX_DIR(config)
AM_INIT_AUTOMAKE(my_package, my_version) AM_INIT_AUTOMAKE(my_package, my_version)
dnl AM_MAINTAINER_MODE dnl AM_MAINTAINER_MODE
@ -53,9 +54,20 @@ AC_FUNC_MALLOC
AC_FUNC_REALLOC AC_FUNC_REALLOC
AC_CHECK_FUNCS([bzero gettimeofday memmove memset strchr strcspn strdup strndup strrchr strspn]) AC_CHECK_FUNCS([bzero gettimeofday memmove memset strchr strcspn strdup strndup strrchr strspn])
# Check for gpgme
AM_PATH_GPGME
GPGME_SUPPORT="yes"
AC_CHECK_LIB(gpgme, gpgme_check_version, , GPGME_SUPPORT="no")
AC_CONFIG_FILES([Makefile AC_CONFIG_FILES([Makefile
fko/Makefile fko/Makefile
doc/Makefile doc/Makefile
src/Makefile]) src/Makefile])
AC_OUTPUT AC_OUTPUT
echo "
libfko v${VERSION} has been configured.
GPG encryption support: $GPGME_SUPPORT
"

View File

@ -354,7 +354,7 @@ gcc -o foo foo.c -I/opt/fko/include -L/opt/fko/lib -lfko
@cindex message digest types @cindex message digest types
@cindex default message digest @cindex default message digest
The fwknop system employs an message digest hash of the @acronym{SPA} The fwknop system employs a message digest hash of the @acronym{SPA}
data as one of the data fields to act a signature which can be used data as one of the data fields to act a signature which can be used
at the receiving end to verify the data is valid. This provides a means at the receiving end to verify the data is valid. This provides a means
to ensure the data was not modified in-transit. The resulting digest to ensure the data was not modified in-transit. The resulting digest

View File

@ -7,7 +7,7 @@ libfko_source_files = \
fko_nat_access.c fko_rand_value.c fko_server_auth.c fko.h fko_limits.h \ fko_nat_access.c fko_rand_value.c fko_server_auth.c fko.h fko_limits.h \
fko_timestamp.c fko_types.h fko_user.c fko_util.h md5.c md5.h \ fko_timestamp.c fko_types.h fko_user.c fko_util.h md5.c md5.h \
rijndael.c rijndael.h sha1.c sha256.c sha.h strlcat.c \ rijndael.c rijndael.h sha1.c sha256.c sha.h strlcat.c \
strlcpy.c fko_state.h fko_context.h strlcpy.c fko_state.h fko_context.h gpgme_funcs.c gpgme_funcs.h
libfko_la_SOURCES = $(libfko_source_files) libfko_la_SOURCES = $(libfko_source_files)
libfko_la_LDFLAGS = -version-info 0:1:0 libfko_la_LDFLAGS = -version-info 0:1:0

View File

@ -35,7 +35,7 @@
/* Get random data. /* Get random data.
*/ */
void void
get_random_data(unsigned char *data, int len) get_random_data(unsigned char *data, size_t len)
{ {
FILE *rfd; FILE *rfd;
struct timeval tv; struct timeval tv;
@ -64,20 +64,23 @@ get_random_data(unsigned char *data, int len)
} }
} }
/* Function to generate initial salt and initialization vector (iv).
* This is is done to be compatible with the data produced via /*** These are Rijndael-specific functions ***/
/* Rijndael function to generate initial salt and initialization vector
* (iv). This is is done to be compatible with the data produced via
* the Perl Crypt::CBC module's use of Rijndael. * the Perl Crypt::CBC module's use of Rijndael.
*/ */
void void
salt_and_iv(RIJNDAEL_context *ctx, const char *pass, unsigned char *data) rij_salt_and_iv(RIJNDAEL_context *ctx, const char *pass, unsigned char *data)
{ {
char pw_buf[16]; char pw_buf[16];
unsigned char tmp_buf[64]; /* How big does this need to be? */ unsigned char tmp_buf[64]; /* How big does this need to be? */
unsigned char kiv_buf[48]; /* Key and IV buffer */ unsigned char kiv_buf[48]; /* Key and IV buffer */
unsigned char md5_buf[16]; /* Buffer for computed md5 hash */ unsigned char md5_buf[16]; /* Buffer for computed md5 hash */
int kiv_len = 0; size_t kiv_len = 0;
int plen = strlen(pass); size_t plen = strlen(pass);
/* First make pw 16 bytes (pad with "0" (ascii 0x30)) or truncate. /* First make pw 16 bytes (pad with "0" (ascii 0x30)) or truncate.
* Note: pw_buf was initialized with '0' chars (again, not the value * Note: pw_buf was initialized with '0' chars (again, not the value
@ -144,7 +147,7 @@ rijndael_init(RIJNDAEL_context *ctx, const char *pass, unsigned char *data)
/* Generate the salt and initialization vector. /* Generate the salt and initialization vector.
*/ */
salt_and_iv(ctx, pass, data); rij_salt_and_iv(ctx, pass, data);
/* Intialize our rinjdael context. /* Intialize our rinjdael context.
*/ */
@ -154,8 +157,8 @@ rijndael_init(RIJNDAEL_context *ctx, const char *pass, unsigned char *data)
/* Take a chunk of data, encrypt it in the same way the perl Crypt::CBC /* Take a chunk of data, encrypt it in the same way the perl Crypt::CBC
* module would. * module would.
*/ */
int size_t
fko_encrypt(unsigned char *in, int in_len, const char *pass, unsigned char *out) rij_encrypt(unsigned char *in, size_t in_len, const char *pass, unsigned char *out)
{ {
RIJNDAEL_context ctx; RIJNDAEL_context ctx;
unsigned char plaintext[16]; unsigned char plaintext[16];
@ -208,8 +211,8 @@ fko_encrypt(unsigned char *in, int in_len, const char *pass, unsigned char *out)
/* Decrypt the given data. /* Decrypt the given data.
*/ */
int size_t
fko_decrypt(unsigned char *in, int in_len, const char *pass, unsigned char *out) rij_decrypt(unsigned char *in, size_t in_len, const char *pass, unsigned char *out)
{ {
RIJNDAEL_context ctx; RIJNDAEL_context ctx;
unsigned char plaintext[16]; unsigned char plaintext[16];
@ -271,5 +274,9 @@ fko_decrypt(unsigned char *in, int in_len, const char *pass, unsigned char *out)
return(ondx - out); return(ondx - out);
} }
/*** These are GPG-specific functions ***/
//--DSS TODO: Finish me
/***EOF***/ /***EOF***/

View File

@ -26,6 +26,7 @@
#include "fko_common.h" #include "fko_common.h"
#include "rijndael.h" #include "rijndael.h"
#include "gpgme_funcs.h"
/* Provide the predicted encrypted data size for given input data based /* Provide the predicted encrypted data size for given input data based
* on a 16-byte block size (for Rijndael implementation,this also accounts * on a 16-byte block size (for Rijndael implementation,this also accounts
@ -33,9 +34,13 @@
*/ */
#define PREDICT_ENCSIZE(x) (1+(x>>4)+(x&0xf?1:0))<<4 #define PREDICT_ENCSIZE(x) (1+(x>>4)+(x&0xf?1:0))<<4
int fko_encrypt(uchar *in, int len, const char *key, uchar *out); size_t rij_encrypt(unsigned char *in, size_t len, const char *key, unsigned char *out);
int fko_decrypt(uchar *in, int len, const char *key, uchar *out); size_t rij_decrypt(unsigned char *in, size_t len, const char *key, unsigned char *out);
void hex_dump(uchar *data, int size);
#if HAVE_LIBGPGME
int gpg_encrypt(unsigned char *in, size_t len, const char *signer, const char *recip, unsigned char **out, size_t *out_sz);
int gpg_decrypt(unsigned char *in, size_t len, const char *key, unsigned char **out, size_t *out_sz);
#endif /* HAVE_LIBGPGME */
#endif /* CIPHER_FUNCS_H */ #endif /* CIPHER_FUNCS_H */

View File

@ -81,6 +81,8 @@ typedef enum {
FKO_ERROR_INVALID_SPA_ACCESS_MSG, FKO_ERROR_INVALID_SPA_ACCESS_MSG,
FKO_ERROR_INVALID_SPA_NAT_ACCESS_MSG, FKO_ERROR_INVALID_SPA_NAT_ACCESS_MSG,
FKO_ERROR_INVALID_ENCRYPTION_TYPE, FKO_ERROR_INVALID_ENCRYPTION_TYPE,
FKO_ERROR_WRONG_ENCRYPTION_TYPE,
FKO_ERROR_MISSING_GPG_KEY_DATA,
FKO_ERROR_DECRYPTION_SIZE_ERROR, FKO_ERROR_DECRYPTION_SIZE_ERROR,
FKO_ERROR_DIGEST_VERIFICATION_FAILED, FKO_ERROR_DIGEST_VERIFICATION_FAILED,
/* Add more errors above this line */ /* Add more errors above this line */
@ -147,6 +149,12 @@ short fko_get_spa_encryption_type(fko_ctx_t ctx);
char* fko_version(fko_ctx_t ctx); char* fko_version(fko_ctx_t ctx);
/* GPG-related functions */
int fko_set_gpg_recipient(fko_ctx_t ctx, const char *recip);
char* fko_get_gpg_recipient(fko_ctx_t ctx);
int fko_set_gpg_signer(fko_ctx_t ctx, const char *signer);
char* fko_get_gpg_signer(fko_ctx_t ctx);
#endif /* FKO_H */ #endif /* FKO_H */
/***EOF***/ /***EOF***/

View File

@ -45,7 +45,7 @@ fko_set_spa_client_timeout(fko_ctx_t ctx, int timeout)
ctx->client_timeout = timeout; ctx->client_timeout = timeout;
ctx->state |= FKO_CLIENT_TIMEOUT_MODIFIED; ctx->state |= FKO_DATA_MODIFIED;
/* If a timeout is set, then we may need to verify/change message /* If a timeout is set, then we may need to verify/change message
* type accordingly. * type accordingly.

View File

@ -26,6 +26,8 @@
#ifndef FKO_CONTEXT_H #ifndef FKO_CONTEXT_H
#define FKO_CONTEXT_H 1 #define FKO_CONTEXT_H 1
#include "fko_common.h"
/* The pieces we need to make an FKO SPA data packet. /* The pieces we need to make an FKO SPA data packet.
*/ */
struct fko_context { struct fko_context {
@ -54,6 +56,12 @@ struct fko_context {
/* State info */ /* State info */
unsigned short state; unsigned short state;
unsigned char initval; unsigned char initval;
#if HAVE_LIBGPGME
/* For gpgme support */
char *gpg_recipient;
char *gpg_signer;
#endif /* HAVE_LIBGPGME */
}; };
#endif /* FKO_CONTEXT_H */ #endif /* FKO_CONTEXT_H */

View File

@ -97,15 +97,15 @@ fko_decode_spa_data(fko_ctx_t ctx)
switch(ctx->digest_type) switch(ctx->digest_type)
{ {
case FKO_DIGEST_MD5: case FKO_DIGEST_MD5:
md5_base64(tbuf, ctx->encoded_msg, strlen(ctx->encoded_msg)); md5_base64(tbuf, (unsigned char*)ctx->encoded_msg, strlen(ctx->encoded_msg));
break; break;
case FKO_DIGEST_SHA1: case FKO_DIGEST_SHA1:
sha1_base64(tbuf, ctx->encoded_msg, strlen(ctx->encoded_msg)); sha1_base64(tbuf, (unsigned char*)ctx->encoded_msg, strlen(ctx->encoded_msg));
break; break;
case FKO_DIGEST_SHA256: case FKO_DIGEST_SHA256:
sha256_base64(tbuf, ctx->encoded_msg, strlen(ctx->encoded_msg)); sha256_base64(tbuf, (unsigned char*)ctx->encoded_msg, strlen(ctx->encoded_msg));
break; break;
} }

View File

@ -30,8 +30,8 @@
#include "base64.h" #include "base64.h"
#include "digest.h" #include "digest.h"
/* A rough way to make enough space for a base64 encoded version of /* Take a given string, base64-encode it and append it to the given
* the given string, encode it, and return it. * buffer.
*/ */
int int
append_b64(char* tbuf, char *str) append_b64(char* tbuf, char *str)
@ -63,7 +63,7 @@ int
fko_encode_spa_data(fko_ctx_t ctx) fko_encode_spa_data(fko_ctx_t ctx)
{ {
int res, offset = 0; int res, offset = 0;
char tbuf[FKO_ENCODE_TMP_BUF_SIZE] = {0}; char *tbuf;
/* Must be initialized /* Must be initialized
*/ */
@ -88,6 +88,12 @@ fko_encode_spa_data(fko_ctx_t ctx)
return(FKO_ERROR_INCOMPLETE_SPA_DATA); return(FKO_ERROR_INCOMPLETE_SPA_DATA);
} }
/* Allocate our initial tmp buffer.
*/
tbuf = calloc(1, FKO_ENCODE_TMP_BUF_SIZE);
if(tbuf == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
/* Put it together a piece at a time, starting with the rand val. /* Put it together a piece at a time, starting with the rand val.
*/ */
strcpy(tbuf, ctx->rand_val); strcpy(tbuf, ctx->rand_val);
@ -96,7 +102,10 @@ fko_encode_spa_data(fko_ctx_t ctx)
*/ */
strlcat(tbuf, ":", FKO_ENCODE_TMP_BUF_SIZE); strlcat(tbuf, ":", FKO_ENCODE_TMP_BUF_SIZE);
if((res = append_b64(tbuf, ctx->username)) != FKO_SUCCESS) if((res = append_b64(tbuf, ctx->username)) != FKO_SUCCESS)
{
free(tbuf);
return(res); return(res);
}
/* Add the timestamp. /* Add the timestamp.
*/ */
@ -126,7 +135,10 @@ fko_encode_spa_data(fko_ctx_t ctx)
/* Add the base64-encoded SPA message. /* Add the base64-encoded SPA message.
*/ */
if((res = append_b64(tbuf, ctx->message)) != FKO_SUCCESS) if((res = append_b64(tbuf, ctx->message)) != FKO_SUCCESS)
{
free(tbuf);
return(res); return(res);
}
/* If a nat_access message was given, add it to the SPA /* If a nat_access message was given, add it to the SPA
* message. * message.
@ -135,7 +147,10 @@ fko_encode_spa_data(fko_ctx_t ctx)
{ {
strlcat(tbuf, ":", FKO_ENCODE_TMP_BUF_SIZE); strlcat(tbuf, ":", FKO_ENCODE_TMP_BUF_SIZE);
if((res = append_b64(tbuf, ctx->nat_access)) != FKO_SUCCESS) if((res = append_b64(tbuf, ctx->nat_access)) != FKO_SUCCESS)
return(res); {
free(tbuf);
return(res);
}
} }
/* If we have a server_auth field set. Add it here. /* If we have a server_auth field set. Add it here.
@ -145,7 +160,10 @@ fko_encode_spa_data(fko_ctx_t ctx)
{ {
strlcat(tbuf, ":", FKO_ENCODE_TMP_BUF_SIZE); strlcat(tbuf, ":", FKO_ENCODE_TMP_BUF_SIZE);
if((res = append_b64(tbuf, ctx->server_auth)) != FKO_SUCCESS) if((res = append_b64(tbuf, ctx->server_auth)) != FKO_SUCCESS)
return(res); {
free(tbuf);
return(res);
}
} }
/* If a client timeout is specified and we are not dealing with a /* If a client timeout is specified and we are not dealing with a
@ -167,17 +185,25 @@ fko_encode_spa_data(fko_ctx_t ctx)
*/ */
ctx->encoded_msg = strdup(tbuf); ctx->encoded_msg = strdup(tbuf);
if(ctx->encoded_msg == NULL) if(ctx->encoded_msg == NULL)
{
free(tbuf);
return(FKO_ERROR_MEMORY_ALLOCATION); return(FKO_ERROR_MEMORY_ALLOCATION);
}
/* At this point we can compute the digest for this SPA data. /* At this point we can compute the digest for this SPA data.
*/ */
if((res = fko_set_spa_digest(ctx)) != FKO_SUCCESS) if((res = fko_set_spa_digest(ctx)) != FKO_SUCCESS)
{
free(tbuf);
return(res); return(res);
}
/* Here we can clear the modified flags on the SPA data fields. /* Here we can clear the modified flags on the SPA data fields.
*/ */
FKO_CLEAR_SPA_DATA_MODIFIED(ctx); FKO_CLEAR_SPA_DATA_MODIFIED(ctx);
free(tbuf);
return(FKO_SUCCESS); return(FKO_SUCCESS);
} }
@ -186,8 +212,6 @@ fko_encode_spa_data(fko_ctx_t ctx)
char* char*
fko_get_encoded_data(fko_ctx_t ctx) fko_get_encoded_data(fko_ctx_t ctx)
{ {
int res;
/* Must be initialized /* Must be initialized
*/ */
if(!CTX_INITIALIZED(ctx)) if(!CTX_INITIALIZED(ctx))

View File

@ -30,6 +30,179 @@
#define B64_RIJNDAEL_SALT "U2FsdGVkX1" #define B64_RIJNDAEL_SALT "U2FsdGVkX1"
/* Prep and encrypt using Rijndael
*/
int
_rijndael_encrypt(fko_ctx_t ctx, const char *enc_key)
{
char *plain;
char *b64cipher;
unsigned char *cipher;
int cipher_len;
/* Make a bucket big enough to hold the enc msg + digest (plaintext)
* and populate it appropriately.
*/
plain = malloc(strlen(ctx->encoded_msg) + strlen(ctx->digest) + 2);
if(plain == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
sprintf(plain, "%s:%s", ctx->encoded_msg, ctx->digest);
/* Make a bucket for the encrypted version and populate it.
*/
cipher = malloc(strlen(plain) + 32); /* Plus padding for salt and Block */
if(cipher == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
cipher_len = rij_encrypt(
(unsigned char*)plain, strlen(plain), (char*)enc_key, cipher
);
/* Now make a bucket for the base64-encoded version and populate it.
*/
b64cipher = malloc(((cipher_len / 3) * 4) + 8);
if(b64cipher == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
b64_encode(cipher, b64cipher, cipher_len);
strip_b64_eq(b64cipher);
ctx->encrypted_msg = strdup(b64cipher);
/* Clean-up
*/
free(plain);
free(cipher);
free(b64cipher);
if(ctx->encrypted_msg == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
return(FKO_SUCCESS);
}
/* Decode, decrypt, and parse SPA data into the context.
*/
int
_rijndael_decrypt(fko_ctx_t ctx, const char *dec_key, int b64_len)
{
char *tbuf;
unsigned char *cipher;
int cipher_len, pt_len;
/* Now see if we need to add the "Salted__" string to the front of the
* encrypted data.
*/
if(strncmp(ctx->encrypted_msg, B64_RIJNDAEL_SALT, strlen(B64_RIJNDAEL_SALT)))
{
/* We need to realloc space for the salt.
*/
tbuf = realloc(ctx->encrypted_msg, b64_len + 12);
if(tbuf == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
memmove(tbuf+10, tbuf, b64_len);
ctx->encrypted_msg = memcpy(tbuf, B64_RIJNDAEL_SALT, strlen(B64_RIJNDAEL_SALT));
}
/* Create a bucket for the (base64) decoded encrypted data and get the
* raw cipher data.
*/
cipher = malloc(strlen(ctx->encrypted_msg));
if(cipher == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
cipher_len = b64_decode(ctx->encrypted_msg, cipher, b64_len);
/* Create a bucket for the plaintext data and decrypt the message
* data into it.
*/
ctx->encoded_msg = malloc(cipher_len);
if(ctx->encoded_msg == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
pt_len = rij_decrypt(cipher, cipher_len, dec_key, (unsigned char*)ctx->encoded_msg);
/* Done with cipher...
*/
free(cipher);
/* The length of the decrypted data should be within 16 of the
* length of the encrypted version.
*/
if(pt_len < (cipher_len - 32))
return(FKO_ERROR_DECRYPTION_SIZE_ERROR);
/* Call fko_decode and return the results.
*/
return(fko_decode_spa_data(ctx));
}
#if HAVE_LIBGPGME
/* Prep and encrypt using gpgme
*/
int
_gpg_encrypt(fko_ctx_t ctx, const char *enc_key)
{
int res;
char *plain;
char *b64cipher;
unsigned char *cipher;
size_t cipher_len;
/* First make sure we have signer and recipient keys set.
*/
if(ctx->gpg_signer == NULL || ctx->gpg_recipient == NULL)
return(FKO_ERROR_MISSING_GPG_KEY_DATA);
/* Make a bucket big enough to hold the enc msg + digest (plaintext)
* and populate it appropriately.
*/
plain = malloc(strlen(ctx->encoded_msg) + strlen(ctx->digest) + 2);
if(plain == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
sprintf(plain, "%s:%s", ctx->encoded_msg, ctx->digest);
res = gpgme_encrypt(
(unsigned char*)plain, strlen(plain),
ctx->gpg_signer, ctx->gpg_recipient,
enc_key, &cipher, &cipher_len
);
/* --DSS XXX: Better parsing of what went wrong would be nice :)
*/
if(res != FKO_SUCCESS)
return(res);
/* Now make a bucket for the base64-encoded version and populate it.
*/
b64cipher = malloc(((cipher_len / 3) * 4) + 8);
if(b64cipher == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
b64_encode(cipher, b64cipher, cipher_len);
strip_b64_eq(b64cipher);
ctx->encrypted_msg = strdup(b64cipher);
/* Clean-up
*/
free(plain);
free(cipher);
free(b64cipher);
if(ctx->encrypted_msg == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
return(FKO_SUCCESS);
}
#endif /* HAVE_LIBGPGME */
/* Set the SPA encryption type. /* Set the SPA encryption type.
*/ */
int int
@ -68,10 +241,7 @@ fko_get_spa_encryption_type(fko_ctx_t ctx)
int int
fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key) fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key)
{ {
char *plain; int res;
char *b64cipher;
unsigned char *cipher;
int cipher_len, res;
/* Must be initialized /* Must be initialized
*/ */
@ -81,7 +251,7 @@ fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key)
/* If there is no encoded data or the SPA data has been modified, /* If there is no encoded data or the SPA data has been modified,
* go ahead and re-encode here. * go ahead and re-encode here.
*/ */
if(ctx->encoded_msg == NULL || FKO_SPA_DATA_MODIFIED(ctx)) if(ctx->encoded_msg == NULL || FKO_IS_SPA_DATA_MODIFIED(ctx))
{ {
res = fko_encode_spa_data(ctx); res = fko_encode_spa_data(ctx);
@ -96,46 +266,20 @@ fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key)
if(strlen(ctx->encoded_msg) < MIN_SPA_ENCODED_MSG_SIZE) if(strlen(ctx->encoded_msg) < MIN_SPA_ENCODED_MSG_SIZE)
return(FKO_ERROR_MISSING_ENCODED_DATA); return(FKO_ERROR_MISSING_ENCODED_DATA);
/* Make a bucket big enough to hold the enc msg + digest (plaintext) /* Encrypt according to type and return...
* and populate it appropriately.
*/ */
plain = malloc(strlen(ctx->encoded_msg) + strlen(ctx->digest) + 2); if(ctx->encryption_type == FKO_ENCRYPTION_RIJNDAEL)
if(plain == NULL) return(_rijndael_encrypt(ctx, enc_key));
return(FKO_ERROR_MEMORY_ALLOCATION);
sprintf(plain, "%s:%s", ctx->encoded_msg, ctx->digest); else if(ctx->encryption_type == FKO_ENCRYPTION_GPG)
#if HAVE_LIBGPGME
return(_gpg_encrypt(ctx, enc_key));
#else
return(FKO_ERROR_UNSUPPORTED_FEATURE);
#endif
/* Make a bucket for the encrypted version and populate it. else
*/ return(FKO_ERROR_INVALID_ENCRYPTION_TYPE);
cipher = malloc(strlen(plain) + 32); /* Plus padding for salt and Block */
if(cipher == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
cipher_len = fko_encrypt(
(unsigned char*)plain, strlen(plain), (char*)enc_key, cipher
);
/* Now make a bucket for the base64-encoded version and populate it.
*/
b64cipher = malloc(((cipher_len / 3) * 4) + 8);
if(b64cipher == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
b64_encode(cipher, b64cipher, cipher_len);
strip_b64_eq(b64cipher);
ctx->encrypted_msg = strdup(b64cipher);
/* Clean-up
*/
free(plain);
free(cipher);
free(b64cipher);
if(ctx->encrypted_msg == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
return(FKO_SUCCESS);
} }
/* Decode, decrypt, and parse SPA data into the context. /* Decode, decrypt, and parse SPA data into the context.
@ -143,9 +287,7 @@ fko_encrypt_spa_data(fko_ctx_t ctx, const char *enc_key)
int int
fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key) fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key)
{ {
char *tbuf; int b64_len;
unsigned char *cipher;
int b64_len, cipher_len, pt_len;
/* First, make sure we have data to work with. /* First, make sure we have data to work with.
*/ */
@ -154,65 +296,116 @@ fko_decrypt_spa_data(fko_ctx_t ctx, const char *dec_key)
return(FKO_ERROR_INVALID_DATA); return(FKO_ERROR_INVALID_DATA);
/* Determine type of encryption used. For know, we are using the /* Determine type of encryption used. For know, we are using the
* size of the message. However, we will want to come up with a * size of the message.
* more reliable method of identification. *
* XXX: We will want to come up with a more reliable method of
* identifying the encryption type.
*/ */
b64_len = strlen(ctx->encrypted_msg); b64_len = strlen(ctx->encrypted_msg);
if(b64_len > MIN_GNUPG_MSG_SIZE) if(b64_len > MIN_GNUPG_MSG_SIZE)
{ {
/* TODO: add GPG handling */ ctx->encryption_type = FKO_ENCRYPTION_GPG;
/* Since we do not support GPG yet, we will just fall through */ #if HAVE_LIBGPGME
return(FKO_ERROR_UNSUPPORTED_FEATURE);
//return(_gpg_decrypt(ctx, dec_key));
#else
return(FKO_ERROR_UNSUPPORTED_FEATURE);
#endif
} }
else /* We are assuming the default of Rijndael */
/* Assuming Rijndael */
/* Now see if we need to add the "Salted__" string to the front of the
* encrypted data.
*/
if(strncmp(ctx->encrypted_msg, B64_RIJNDAEL_SALT, strlen(B64_RIJNDAEL_SALT)))
{ {
/* We need to realloc space for the salt. ctx->encryption_type = FKO_ENCRYPTION_RIJNDAEL;
*/ return(_rijndael_decrypt(ctx, dec_key, b64_len));
tbuf = realloc(ctx->encrypted_msg, b64_len + 12);
if(tbuf == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
memmove(tbuf+10, tbuf, b64_len);
ctx->encrypted_msg = memcpy(tbuf, B64_RIJNDAEL_SALT, strlen(B64_RIJNDAEL_SALT));
} }
}
/* Create a bucket for the (base64) decoded encrypted data and get the /* Set the GPG recipient key name.
* raw cipher data. */
int
fko_set_gpg_recipient(fko_ctx_t ctx, const char *recip)
{
#if HAVE_LIBGPGME
/* Must be initialized
*/ */
cipher = malloc(strlen(ctx->encrypted_msg)); if(!CTX_INITIALIZED(ctx))
if(cipher == NULL) return(FKO_ERROR_CTX_NOT_INITIALIZED);
return(FKO_ERROR_MEMORY_ALLOCATION);
cipher_len = b64_decode(ctx->encrypted_msg, cipher, b64_len);
/* Create a bucket for the plaintext data and decrypt the message if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
* data into it. return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
*/
ctx->encoded_msg = malloc(cipher_len); ctx->gpg_recipient = strdup(recip);
if(ctx->encoded_msg == NULL) if(ctx->gpg_recipient == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION); return(FKO_ERROR_MEMORY_ALLOCATION);
pt_len = fko_decrypt(cipher, cipher_len, dec_key, (unsigned char*)ctx->encoded_msg); ctx->state |= FKO_DATA_MODIFIED;
/* Done with cipher...
*/
free(cipher);
/* The length of the decrypted data should be within 16 of the return(FKO_SUCCESS);
* length of the encrypted version. #else
*/ return(FKO_ERROR_UNSUPPORTED_FEATURE);
if(pt_len < (cipher_len - 32)) #endif /* HAVE_LIBGPGME */
return(FKO_ERROR_DECRYPTION_SIZE_ERROR); }
/* Call fko_decode and return the results. /* Get the GPG recipient key name.
*/
char*
fko_get_gpg_recipient(fko_ctx_t ctx)
{
#if HAVE_LIBGPGME
/* Must be initialized
*/ */
return(fko_decode_spa_data(ctx)); if(!CTX_INITIALIZED(ctx))
return(NULL);
return(ctx->gpg_recipient);
#else
//--DSS we should make this an error
return(NULL);
#endif /* HAVE_LIBGPGME */
}
/* Set the GPG signer key name.
*/
int
fko_set_gpg_signer(fko_ctx_t ctx, const char *signer)
{
#if HAVE_LIBGPGME
/* Must be initialized
*/
if(!CTX_INITIALIZED(ctx))
return(FKO_ERROR_CTX_NOT_INITIALIZED);
if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
ctx->gpg_signer = strdup(signer);
if(ctx->gpg_signer == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION);
ctx->state |= FKO_DATA_MODIFIED;
return(FKO_SUCCESS);
#else
return(FKO_ERROR_UNSUPPORTED_FEATURE);
#endif /* HAVE_LIBGPGME */
}
/* Get the GPG signer key name.
*/
char*
fko_get_gpg_signer(fko_ctx_t ctx)
{
#if HAVE_LIBGPGME
/* Must be initialized
*/
if(!CTX_INITIALIZED(ctx))
return(NULL);
return(ctx->gpg_signer);
#else
//--DSS we should make this an error
return(NULL);
#endif /* HAVE_LIBGPGME */
} }
/***EOF***/ /***EOF***/

View File

@ -44,6 +44,8 @@ static const char *fko_err_msgs[] = {
"Invalid SPA access mesage format", "Invalid SPA access mesage format",
"Invalid SPA nat_access mesage format", "Invalid SPA nat_access mesage format",
"Invalid encryption type", "Invalid encryption type",
"Wrong or inappropriate encryption type for this operation",
"Missing GPG key data (signer or recipient not set)",
"Unexpected or invalid size for decrypted data", "Unexpected or invalid size for decrypted data",
"The computed digest did not match the digest in the spa data", "The computed digest did not match the digest in the spa data",
"Unsupported or unimplemented feature or function", "Unsupported or unimplemented feature or function",

View File

@ -209,6 +209,14 @@ fko_destroy(fko_ctx_t ctx)
if(ctx->encrypted_msg != NULL) if(ctx->encrypted_msg != NULL)
free(ctx->encrypted_msg); free(ctx->encrypted_msg);
#if HAVE_LIBGPGME
if(ctx->gpg_recipient != NULL)
free(ctx->gpg_recipient);
if(ctx->gpg_signer != NULL)
free(ctx->gpg_signer);
#endif /* HAVE_LIBGPGME */
bzero(ctx, sizeof(fko_ctx_t)); bzero(ctx, sizeof(fko_ctx_t));
} }
@ -235,8 +243,6 @@ fko_version(fko_ctx_t ctx)
int int
fko_spa_data_final(fko_ctx_t ctx, const char *enc_key) fko_spa_data_final(fko_ctx_t ctx, const char *enc_key)
{ {
int res;
/* Must be initialized /* Must be initialized
*/ */
if(!CTX_INITIALIZED(ctx)) if(!CTX_INITIALIZED(ctx))
@ -250,8 +256,6 @@ fko_spa_data_final(fko_ctx_t ctx, const char *enc_key)
char* char*
fko_get_spa_data(fko_ctx_t ctx) fko_get_spa_data(fko_ctx_t ctx)
{ {
int res;
/* Must be initialized /* Must be initialized
*/ */
if(!CTX_INITIALIZED(ctx)) if(!CTX_INITIALIZED(ctx))

View File

@ -123,7 +123,7 @@ fko_set_spa_message(fko_ctx_t ctx, const char *msg)
ctx->message = strdup(msg); ctx->message = strdup(msg);
ctx->state |= FKO_SPA_MSG_MODIFIED; ctx->state |= FKO_DATA_MODIFIED;
if(ctx->message == NULL) if(ctx->message == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION); return(FKO_ERROR_MEMORY_ALLOCATION);

View File

@ -55,7 +55,7 @@ fko_set_spa_nat_access(fko_ctx_t ctx, const char *msg)
ctx->nat_access = strdup(msg); ctx->nat_access = strdup(msg);
ctx->state |= FKO_NAT_ACCESS_MODIFIED; ctx->state |= FKO_DATA_MODIFIED;
if(ctx->nat_access == NULL) if(ctx->nat_access == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION); return(FKO_ERROR_MEMORY_ALLOCATION);

View File

@ -61,7 +61,7 @@ fko_set_rand_value(fko_ctx_t ctx, const char *new_val)
if(ctx->rand_val == NULL) if(ctx->rand_val == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION); return(FKO_ERROR_MEMORY_ALLOCATION);
ctx->state |= FKO_RAND_VAL_MODIFIED; ctx->state |= FKO_DATA_MODIFIED;
return(FKO_SUCCESS); return(FKO_SUCCESS);
} }
@ -106,7 +106,7 @@ fko_set_rand_value(fko_ctx_t ctx, const char *new_val)
free(tmp_buf); free(tmp_buf);
ctx->state |= FKO_RAND_VAL_MODIFIED; ctx->state |= FKO_DATA_MODIFIED;
return(FKO_SUCCESS); return(FKO_SUCCESS);
} }

View File

@ -69,7 +69,7 @@ fko_set_spa_server_auth(fko_ctx_t ctx, const char *msg)
ctx->server_auth = strdup(msg); ctx->server_auth = strdup(msg);
ctx->state |= FKO_SERVER_AUTH_MODIFIED; ctx->state |= FKO_DATA_MODIFIED;
if(ctx->server_auth == NULL) if(ctx->server_auth == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION); return(FKO_ERROR_MEMORY_ALLOCATION);

View File

@ -30,19 +30,20 @@
*/ */
typedef enum { typedef enum {
FKO_CTX_SET = 1, /* Set when ctx is initialized */ FKO_CTX_SET = 1, /* Set when ctx is initialized */
FKO_RAND_VAL_MODIFIED = 1 << 1, FKO_DATA_MODIFIED = 1 << 1,
FKO_USERNAME_MODIFIED = 1 << 2, FKO_STATE_RESERVED_2 = 1 << 2,
FKO_TIMESTAMP_MODIFIED = 1 << 3, STATE_RESERVED_3 = 1 << 3,
FKO_VERSION_MODIFIED = 1 << 4, STATE_RESERVED_4 = 1 << 4,
STATE_RESERVED_5 = 1 << 5,
FKO_SPA_MSG_TYPE_MODIFIED = 1 << 6, FKO_SPA_MSG_TYPE_MODIFIED = 1 << 6,
FKO_CTX_SET_2 = 1 << 7, /* Set when ctx is initialized */ FKO_CTX_SET_2 = 1 << 7, /* Set when ctx is initialized */
FKO_SPA_MSG_MODIFIED = 1 << 8, STATE_RESERVED_8 = 1 << 8,
FKO_NAT_ACCESS_MODIFIED = 1 << 9, STATE_RESERVED_9 = 1 << 9,
FKO_SERVER_AUTH_MODIFIED = 1 << 10, STATE_RESERVED_10 = 1 << 10,
FKO_CLIENT_TIMEOUT_MODIFIED = 1 << 11, STATE_RESERVED_11 = 1 << 11,
FKO_DIGEST_TYPE_MODIFIED = 1 << 12, FKO_DIGEST_TYPE_MODIFIED = 1 << 12,
FKO_ENCRYPT_TYPE_MODIFIED = 1 << 13, FKO_ENCRYPT_TYPE_MODIFIED = 1 << 13,
FKO_GPG_SUPPORTED = 1 << 14, STATE_RESERVED_14 = 1 << 14,
FKO_BACKWARD_COMPATIBLE = 1 << 15 FKO_BACKWARD_COMPATIBLE = 1 << 15
} fko_state_flags_t; } fko_state_flags_t;
@ -62,23 +63,20 @@ typedef enum {
/* Consolidate all SPA data modified flags. /* Consolidate all SPA data modified flags.
*/ */
#define FKO_ANY_SPA_DATA_MODIFIED ( \ #define FKO_SPA_DATA_MODIFIED ( \
FKO_RAND_VAL_MODIFIED | FKO_USERNAME_MODIFIED | FKO_TIMESTAMP_MODIFIED \ FKO_DATA_MODIFIED | FKO_SPA_MSG_TYPE_MODIFIED \
| FKO_VERSION_MODIFIED | FKO_SPA_MSG_TYPE_MODIFIED | FKO_SPA_MSG_MODIFIED \ | FKO_DIGEST_TYPE_MODIFIED | FKO_ENCRYPT_TYPE_MODIFIED )
| FKO_NAT_ACCESS_MODIFIED | FKO_SERVER_AUTH_MODIFIED \
| FKO_CLIENT_TIMEOUT_MODIFIED | FKO_DIGEST_TYPE_MODIFIED \
| FKO_ENCRYPT_TYPE_MODIFIED )
/* This should return true if any SPA data field has been modifed since the /* This should return true if any SPA data field has been modifed since the
* last encode/encrypt. * last encode/encrypt.
*/ */
#define FKO_SPA_DATA_MODIFIED(ctx) (ctx->state & FKO_ANY_SPA_DATA_MODIFIED) #define FKO_IS_SPA_DATA_MODIFIED(ctx) (ctx->state & FKO_SPA_DATA_MODIFIED)
/* Clear all SPA data modified flags. This is normally called after a /* Clear all SPA data modified flags. This is normally called after a
* succesful encode/digest/encryption cycle. * succesful encode/digest/encryption cycle.
*/ */
#define FKO_CLEAR_SPA_DATA_MODIFIED(ctx) \ #define FKO_CLEAR_SPA_DATA_MODIFIED(ctx) \
(ctx->state &= (0xffff & ~FKO_ANY_SPA_DATA_MODIFIED)) (ctx->state &= (0xffff & ~FKO_SPA_DATA_MODIFIED))
/* Macros used for determining ctx initialization state. /* Macros used for determining ctx initialization state.
*/ */

View File

@ -52,7 +52,7 @@ fko_set_timestamp(fko_ctx_t ctx, int offset)
ctx->timestamp = ts; ctx->timestamp = ts;
ctx->state |= FKO_TIMESTAMP_MODIFIED; ctx->state |= FKO_DATA_MODIFIED;
return(FKO_SUCCESS); return(FKO_SUCCESS);
} }

View File

@ -82,7 +82,7 @@ fko_set_username(fko_ctx_t ctx, const char *spoof_user)
ctx->username = strdup(username); ctx->username = strdup(username);
ctx->state |= FKO_USERNAME_MODIFIED; ctx->state |= FKO_DATA_MODIFIED;
if(ctx->username == NULL) if(ctx->username == NULL)
return(FKO_ERROR_MEMORY_ALLOCATION); return(FKO_ERROR_MEMORY_ALLOCATION);

287
fko/gpgme_funcs.c Normal file
View File

@ -0,0 +1,287 @@
/* $Id$
*****************************************************************************
*
* File: gpgme_funcs.c
*
* Author: Damien S. Stuart
*
* Purpose: gpgme-related functions for GPG encryptions support in libfko.
*
* Copyright (C) 2008 Damien Stuart (dstuart@dstuart.org)
*
* License (GNU Public License):
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*****************************************************************************
*/
#include "fko_common.h"
#if HAVE_LIBGPGME
#include <gpgme.h>
#include "gpgme_funcs.h"
/* Callback function that supplies the password when gpgme needs it.
*/
gpgme_error_t
get_gpg_pw(
void *hook, const char *uid_hint, const char *passphrase_info,
int prev_was_bad, int fd)
{
/* We only need to try once as it is fed by the program
* (for now --DSS).
*/
if(prev_was_bad)
return(GPG_ERR_CANCELED);
write(fd, (const char*)hook, strlen((const char*)hook));
write(fd, "\n", 1);
return 0;
}
/* Get the key for the designated signer and add it to the main gpgme context.
*/
int
set_signer(gpgme_ctx_t ctx, const char *signer)
{
gpgme_error_t err;
gpgme_ctx_t list_ctx;
gpgme_key_t key, key2;
/* Create a gpgme context for the list
*/
err = gpgme_new(&list_ctx);
if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
{
return(gpg_err_code(err));
}
err = gpgme_op_keylist_start(list_ctx, signer, 1);
if (!err)
err = gpgme_op_keylist_next(list_ctx, &key);
if (err)
{
gpgme_release(list_ctx);
//secret key not found
return(gpg_err_code(err));
}
err = gpgme_op_keylist_next(list_ctx, &key2);
if (!err)
{
gpgme_key_release(key);
gpgme_key_release(key2);
gpgme_release(list_ctx);
//ambiguous specfication of secret key
return(gpg_err_code(err));
}
gpgme_op_keylist_end(list_ctx);
gpgme_release(list_ctx);
gpgme_signers_clear(ctx);
err = gpgme_signers_add(ctx, key);
gpgme_key_release(key);
if (err)
{
//error setting secret key
return(gpg_err_code(err));
}
return 0;
}
int
get_recip_key(gpgme_key_t *mykey, const char *recip)
{
gpgme_error_t err;
gpgme_ctx_t list_ctx;
gpgme_key_t key, key2;
/* Create a gpgme context for the list
*/
err = gpgme_new(&list_ctx);
if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
{
return(gpg_err_code(err));
}
err = gpgme_op_keylist_start(list_ctx, recip, 1);
/* Grab the first key in the list (we hope it is the only one).
*/
err = gpgme_op_keylist_next(list_ctx, &key);
if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
{
gpgme_release(list_ctx);
return(gpg_err_code(err));
}
/* We try to get the next key match. If we do, then the name is
* ambiguous, so we return an error.
*/
err = gpgme_op_keylist_next(list_ctx, &key2);
if(gpg_err_code(err) == GPG_ERR_NO_ERROR) /* Note: look for NO error */
{
gpgme_key_release(key);
gpgme_key_release(key2);
gpgme_release(list_ctx);
//ambiguous specfication of secret key
return(gpg_err_code(err));
}
gpgme_op_keylist_end(list_ctx);
//printf("Got Key:\n%s: %s <%s>\n",
// key->subkeys->keyid, key->uids->name, key->uids->email);
/* Make our key the first entry in the array (just more gpgme funkyness).
*/
*mykey = key;
return(0);
}
/* The main GPG encryption routine for libfko.
*/
int
gpgme_encrypt(
unsigned char *indata, size_t in_len, const char *signer, const char *recip,
const char *pw, unsigned char **out, size_t *out_len)
{
char *tmp_buf;
int res;
gpgme_ctx_t gpg_ctx;
gpgme_error_t err;
gpgme_key_t key[2] = {0};
gpgme_data_t data;
gpgme_data_t plaintext;
/* Because the gpgme manual says you should.
*/
gpgme_check_version(NULL);
/* Check for OpenPGP support
*/
err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
{
/* GPG engine is not available. */
return(gpg_err_code(err));
}
/* Create our gpgme context
*/
err = gpgme_new(&gpg_ctx);
if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
{
return(gpg_err_code(err));
}
/* Initialize the plaintext data (place into gpgme_data object)
*/
err = gpgme_data_new_from_mem(&plaintext, (char*)indata, in_len, 1);
if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
{
gpgme_release(gpg_ctx);
return(gpg_err_code(err));
}
/* Set protocol
*/
err = gpgme_set_protocol(gpg_ctx, GPGME_PROTOCOL_OpenPGP);
if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
{
gpgme_release(gpg_ctx);
return(gpg_err_code(err));
}
/* Set ascii-armor off (we will be base64-encoding the encrypted data
* ourselves.
*/
gpgme_set_armor(gpg_ctx, 0);
/* Get the signer gpg key
*/
err = set_signer(gpg_ctx, signer);
if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
{
gpgme_release(gpg_ctx);
return(gpg_err_code(err));
}
/* Get the recipient gpg key
*/
err = get_recip_key((gpgme_key_t*)&key, recip);
if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
{
gpgme_release(gpg_ctx);
return(gpg_err_code(err));
}
/* Create the buffer for our encrypted data.
*/
err = gpgme_data_new(&data);
if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
{
gpgme_release(gpg_ctx);
return(gpg_err_code(err));
}
/* Set the passphrase callback.
*/
gpgme_set_passphrase_cb(gpg_ctx, get_gpg_pw, pw);
err = gpgme_op_encrypt_sign(gpg_ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, data);
if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
{
//fprintf(stderr, "*Ecrypt&Sign Error: %s\n", gpgme_strerror(err));
gpgme_release(gpg_ctx);
return(gpg_err_code(err));
}
/* Get the encrypted data and its length from the gpgme data object.
*/
tmp_buf = gpgme_data_release_and_get_mem(data, out_len);
*out = malloc(*out_len); /* Note: this is freed when the context is destroyed */
if(*out == NULL)
{
res = -2;
}
else
{
res = 0;
memcpy(*out, tmp_buf, *out_len);
}
gpgme_free(tmp_buf);
gpgme_release(gpg_ctx);
return(res);
}
#endif /* HAVE_LIBGPGME */
/***EOF***/

34
fko/gpgme_funcs.h Normal file
View File

@ -0,0 +1,34 @@
/* $Id$
*****************************************************************************
*
* File: gpgme_funcs.h
*
* Author: Damien S. Stuart
*
* Purpose: Header for the fwknop gpgme_funcs.c.
*
* License (GNU Public License):
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*****************************************************************************
*/
#ifndef GPGME_FUNCS_H
#define GPGME_FUNCS_H 1
#include "fko_common.h"
int gpgme_encrypt(unsigned char *in, size_t len, const char *signer, const char *recip, const char *pw, unsigned char **out, size_t *out_len);
int gpgme_decrypt(unsigned char *in, size_t len, const char *pw, unsigned char **out, size_t *out_len);
#endif /* GPGME_FUNCS_H */
/***EOF***/