2 *****************************************************************************
6 * Author: Damien S. Stuart
8 * Purpose: General utility functions for libfko
10 * Copyright 2009-2010 Damien Stuart (dstuart@dstuart.org)
12 * License (GNU Public License):
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29 *****************************************************************************
31 #include "fko_common.h"
33 #include "cipher_funcs.h"
35 /* Initialize an fko context.
38 fko_new(fko_ctx_t *r_ctx)
44 ctx = calloc(1, sizeof *ctx);
46 return(FKO_ERROR_MEMORY_ALLOCATION);
48 /* Set default values and state.
50 * Note: We have to explicitly set the ctx->state to initialized
51 * just before making an fko_xxx function call, then set it
52 * back to zero just afer. During initialization, we need
53 * to make these functions think they are operating on an
54 * initialized context, or else they would fail.
57 /* Set the version string.
59 ctx->initval = FKO_CTX_INITIALIZED;
60 ver = strdup(FKO_PROTOCOL_VERSION);
65 return(FKO_ERROR_MEMORY_ALLOCATION);
72 ctx->initval = FKO_CTX_INITIALIZED;
73 res = fko_set_rand_value(ctx, NULL);
75 if(res != FKO_SUCCESS)
83 ctx->initval = FKO_CTX_INITIALIZED;
84 res = fko_set_username(ctx, NULL);
86 if(res != FKO_SUCCESS)
94 ctx->initval = FKO_CTX_INITIALIZED;
95 res = fko_set_timestamp(ctx, 0);
97 if(res != FKO_SUCCESS)
103 /* Default Digest Type.
105 ctx->initval = FKO_CTX_INITIALIZED;
106 res = fko_set_spa_digest_type(ctx, FKO_DEFAULT_DIGEST);
108 if(res != FKO_SUCCESS)
114 /* Default Message Type.
116 ctx->initval = FKO_CTX_INITIALIZED;
117 res = fko_set_spa_message_type(ctx, FKO_DEFAULT_MSG_TYPE);
119 if(res != FKO_SUCCESS)
125 /* Default Encryption Type.
127 ctx->initval = FKO_CTX_INITIALIZED;
128 res = fko_set_spa_encryption_type(ctx, FKO_DEFAULT_ENCRYPTION);
130 if(res != FKO_SUCCESS)
137 /* Set gpg signature verify on.
139 ctx->verify_gpg_sigs = 1;
141 #endif /* HAVE_LIBGPGME */
145 ctx->initval = FKO_CTX_INITIALIZED;
147 FKO_SET_CTX_INITIALIZED(ctx);
154 /* Initialize an fko context with external (encrypted/encoded) data.
155 * This is used to create a context with the purpose of decoding
156 * and parsing the provided data into the context data.
159 fko_new_with_data(fko_ctx_t *r_ctx, const char *enc_msg, const char *dec_key)
162 int res = FKO_SUCCESS; /* Are we optimistic or what? */
164 ctx = calloc(1, sizeof *ctx);
166 return(FKO_ERROR_MEMORY_ALLOCATION);
168 /* First, add the data to the context.
170 ctx->encrypted_msg = strdup(enc_msg);
171 if(ctx->encrypted_msg == NULL)
174 return(FKO_ERROR_MEMORY_ALLOCATION);
177 /* Consider it initialized here.
179 ctx->initval = FKO_CTX_INITIALIZED;
180 FKO_SET_CTX_INITIALIZED(ctx);
182 /* If a decryption password is provided, go ahead and decrypt and
187 res = fko_decrypt_spa_data(ctx, dec_key);
189 if(res != FKO_SUCCESS)
192 *r_ctx = NULL; /* Make sure the caller ctx is null just in case */
198 /* Set gpg signature verify on.
200 ctx->verify_gpg_sigs = 1;
202 #endif /* HAVE_LIBGPGME */
209 /* Destroy a context and free its resources
212 fko_destroy(fko_ctx_t ctx)
215 fko_gpg_sig_t gsig, tgsig;
218 if(CTX_INITIALIZED(ctx))
220 if(ctx->rand_val != NULL)
223 if(ctx->username != NULL)
226 if(ctx->version != NULL)
229 if(ctx->message != NULL)
232 if(ctx->nat_access != NULL)
233 free(ctx->nat_access);
235 if(ctx->server_auth != NULL)
236 free(ctx->server_auth);
238 if(ctx->digest != NULL)
241 if(ctx->encoded_msg != NULL)
242 free(ctx->encoded_msg);
244 if(ctx->encrypted_msg != NULL)
245 free(ctx->encrypted_msg);
248 if(ctx->gpg_exe != NULL)
251 if(ctx->gpg_home_dir != NULL)
252 free(ctx->gpg_home_dir);
254 if(ctx->gpg_recipient != NULL)
255 free(ctx->gpg_recipient);
257 if(ctx->gpg_signer != NULL)
258 free(ctx->gpg_signer);
260 if(ctx->recipient_key != NULL)
262 gpgme_key_unref(ctx->recipient_key);
265 if(ctx->signer_key != NULL)
267 gpgme_key_unref(ctx->signer_key);
270 if(ctx->gpg_ctx != NULL)
271 gpgme_release(ctx->gpg_ctx);
273 gsig = ctx->gpg_sigs;
276 if(gsig->fpr != NULL)
285 #endif /* HAVE_LIBGPGME */
287 bzero(ctx, sizeof(*ctx));
293 /* Return the fko version
296 fko_get_version(fko_ctx_t ctx, char **version)
298 /* Must be initialized
300 if(!CTX_INITIALIZED(ctx))
301 return(FKO_ERROR_CTX_NOT_INITIALIZED);
303 *version = ctx->version;
308 /* Final update and encoding of data in the context.
309 * This does require all requisite fields be properly
313 fko_spa_data_final(fko_ctx_t ctx, const char *enc_key)
315 /* Must be initialized
317 if(!CTX_INITIALIZED(ctx))
318 return(FKO_ERROR_CTX_NOT_INITIALIZED);
320 return(fko_encrypt_spa_data(ctx, enc_key));
323 /* Return the fko SPA encrypted data.
326 fko_get_spa_data(fko_ctx_t ctx, char **spa_data)
328 /* Must be initialized
330 if(!CTX_INITIALIZED(ctx))
331 return(FKO_ERROR_CTX_NOT_INITIALIZED);
333 /* We expect to have encrypted data to process. If not, we bail.
335 if(ctx->encrypted_msg == NULL || (strlen(ctx->encrypted_msg) < 1))
336 return(FKO_ERROR_MISSING_ENCODED_DATA);
338 *spa_data = ctx->encrypted_msg;
340 /* Notice we omit the first 10 bytes if Rijndael encryption is
341 * used (to eliminate the consistent 'Salted__' string), and
342 * in GnuPG mode we eliminate the consistent 'hQ' base64 encoded
345 if(ctx->encryption_type == FKO_ENCRYPTION_RIJNDAEL)
346 *spa_data += strlen(B64_RIJNDAEL_SALT);
347 else if(ctx->encryption_type == FKO_ENCRYPTION_GPG)
348 *spa_data += strlen(B64_GPG_PREFIX);
353 /* Set the fko SPA encrypted data.
356 fko_set_spa_data(fko_ctx_t ctx, const char *enc_msg)
358 /* Must be initialized
360 if(!CTX_INITIALIZED(ctx))
361 return FKO_ERROR_CTX_NOT_INITIALIZED;
363 /* First, add the data to the context.
365 ctx->encrypted_msg = strdup(enc_msg);
366 if(ctx->encrypted_msg == NULL)
367 return(FKO_ERROR_MEMORY_ALLOCATION);