/* Prep and encrypt using gpgme */ static int gpg_encrypt(fko_ctx_t ctx, const char *enc_key) { int res; char *plain; char *b64cipher; unsigned char *cipher = NULL; size_t cipher_len; /* First make sure we have a recipient key set. */ if(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); snprintf(plain, strlen(ctx->encoded_msg) + strlen(ctx->digest) + 2, "%s:%s", ctx->encoded_msg, ctx->digest); res = gpgme_encrypt(ctx, (unsigned char*)plain, strlen(plain), enc_key, &cipher, &cipher_len ); /* --DSS XXX: Better parsing of what went wrong would be nice :) */ if(res != FKO_SUCCESS) { free(plain); if(cipher) free(cipher); 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); }
/* Prep and encrypt using gpgme */ static int gpg_encrypt(fko_ctx_t ctx, const char *enc_key) { int res; char *plain; int pt_len, zero_free_rv = FKO_SUCCESS; char *b64cipher; unsigned char *cipher = NULL; size_t cipher_len; char *empty_key = ""; if (! is_valid_encoded_msg_len(ctx->encoded_msg_len)) return(FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_MESSAGE_VALIDFAIL); switch(ctx->digest_len) { case MD5_B64_LEN: break; case SHA1_B64_LEN: break; case SHA256_B64_LEN: break; case SHA384_B64_LEN: break; case SHA512_B64_LEN: break; default: return(FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_DIGEST_VALIDFAIL); } /* First make sure we have a recipient key set. */ if(ctx->gpg_recipient == NULL) return(FKO_ERROR_MISSING_GPG_KEY_DATA); pt_len = ctx->encoded_msg_len + ctx->digest_len + 2; /* Make a bucket big enough to hold the enc msg + digest (plaintext) * and populate it appropriately. */ plain = malloc(ctx->encoded_msg_len + ctx->digest_len + 2); if(plain == NULL) return(FKO_ERROR_MEMORY_ALLOCATION); pt_len = snprintf(plain, pt_len+1, "%s:%s", ctx->encoded_msg, ctx->digest); if(! is_valid_pt_msg_len(pt_len)) { if(zero_free(plain, pt_len) == FKO_SUCCESS) return(FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_MSGLEN_VALIDFAIL); else return(FKO_ERROR_ZERO_OUT_DATA); } if (enc_key != NULL) { res = gpgme_encrypt(ctx, (unsigned char*)plain, pt_len, enc_key, &cipher, &cipher_len ); } else { res = gpgme_encrypt(ctx, (unsigned char*)plain, pt_len, empty_key, &cipher, &cipher_len ); } /* --DSS XXX: Better parsing of what went wrong would be nice :) */ if(res != FKO_SUCCESS) { zero_free_rv = zero_free(plain, pt_len); if(cipher != NULL) if(zero_free((char *) cipher, cipher_len) != FKO_SUCCESS) zero_free_rv = FKO_ERROR_ZERO_OUT_DATA; if(zero_free_rv == FKO_SUCCESS) return(res); else return(zero_free_rv); } /* Now make a bucket for the base64-encoded version and populate it. */ b64cipher = malloc(((cipher_len / 3) * 4) + 8); if(b64cipher == NULL) { if(zero_free(plain, pt_len) != FKO_SUCCESS) zero_free_rv = FKO_ERROR_ZERO_OUT_DATA; if(cipher != NULL) if(zero_free((char *) cipher, cipher_len) != FKO_SUCCESS) zero_free_rv = FKO_ERROR_ZERO_OUT_DATA; if(zero_free_rv == FKO_SUCCESS) return(FKO_ERROR_MEMORY_ALLOCATION); else return(zero_free_rv); } b64_encode(cipher, b64cipher, cipher_len); strip_b64_eq(b64cipher); if(ctx->encrypted_msg != NULL) zero_free_rv = zero_free(ctx->encrypted_msg, strnlen(ctx->encrypted_msg, MAX_SPA_ENCODED_MSG_SIZE)); ctx->encrypted_msg = strdup(b64cipher); ctx->encrypted_msg_len = strnlen(ctx->encrypted_msg, MAX_SPA_ENCODED_MSG_SIZE); /* Clean-up */ if(zero_free(plain, pt_len) != FKO_SUCCESS) zero_free_rv = FKO_ERROR_ZERO_OUT_DATA; if(zero_free((char *) cipher, cipher_len) != FKO_SUCCESS) zero_free_rv = FKO_ERROR_ZERO_OUT_DATA; if(zero_free(b64cipher, strnlen(b64cipher, MAX_SPA_ENCODED_MSG_SIZE)) != FKO_SUCCESS) zero_free_rv = FKO_ERROR_ZERO_OUT_DATA; if(ctx->encrypted_msg == NULL) return(FKO_ERROR_MEMORY_ALLOCATION); if(! is_valid_encoded_msg_len(ctx->encrypted_msg_len)) return(FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_RESULT_MSGLEN_VALIDFAIL); return(zero_free_rv); }