ESAPI-C 1.0
The OWASP Enterprise Security API for C

crypto.c

Go to the documentation of this file.
00001 
00020 #include <gcrypt.h>
00021 #include <stdio.h>
00022 #include <stdbool.h>
00023 
00024 #include "crypto.h"
00025 #include "base64.h"
00026 
00027 char esapi_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
00028 
00029 static int verbose;
00030 
00031 #define BUF_SIZE        1024
00032 
00033 char *esapi_encrypt(struct esapi_ctx *ctx, const char *s) {
00034         gcry_error_t err = GPG_ERR_NO_ERROR;
00035         gcry_cipher_hd_t hd;
00036         size_t blk_len = 0;
00037         char *enc_buff = 0;
00038         char *ret = 0;
00039         gcry_error_t key_len = 0;
00040         size_t in_len;
00041         int ret_len = 0;
00042 
00043         if ((err = gcry_cipher_open(&hd, ctx->sym_algo, ctx->sym_algo_mode, 0))
00044                         != 0) {
00045                 (void) fprintf(stderr, "gcry_cipher_open failed:  %s/%s\n",
00046                                 gcry_strsource(err), gcry_strerror(err));
00047                 return 0;
00048         }
00049 
00050         if ((key_len = gcry_cipher_get_algo_keylen(ctx->sym_algo)) == 0) {
00051                 (void) fprintf(stderr, "failed to get key length for %s in %s\n",
00052                                 gcry_cipher_algo_name(ctx->sym_algo), __func__);
00053                 return 0;
00054         }
00055 
00056         if (key_len > sizeof ctx->sym_key) {
00057                 fprintf(stderr, "algo %d, keylength problem %d, in %s\n",
00058                                 ctx->sym_algo, key_len, __func__);
00059                 return 0;
00060         }
00061 
00062         if (ctx->sym_key[0] == '\0') {
00063                 for (int i = 0; i < key_len; i++) {
00064                         ctx->sym_key[i] = i + (clock() & 0x7f);
00065                 }
00066         }
00067 
00068         if ((blk_len = gcry_cipher_get_algo_blklen(ctx->sym_algo)) == 0) {
00069                 (void) fprintf(stderr, "block length problem in %s\n", __func__);
00070                 return 0;
00071         }
00072 
00073         if ((err = gcry_cipher_setkey(hd, ctx->sym_key, key_len)) != 0) {
00074                 (void) fprintf(stderr, "gcry_cipher_setkey failed:  %s/%s\n",
00075                                 gcry_strsource(err), gcry_strerror(err));
00076                 return 0;
00077         }
00078 
00079         if (ctx->master_iv) {
00080                 if ((err = gcry_cipher_setiv(hd, ctx->master_iv, blk_len)) != 0) {
00081                         (void) fprintf(stderr, "gcry_cipher_setiv failed:  %s/%s\n",
00082                                         gcry_strsource(err), gcry_strerror(err));
00083                         return 0;
00084                 }
00085         }
00086 
00087         in_len = BUF_SIZE;
00088 
00089         if ((enc_buff = (char *) malloc(in_len)) == 0) {
00090                 (void) fprintf(stderr, "malloc failure in %s\n", __func__);
00091                 exit(EXIT_FAILURE);
00092         }
00093 
00094         if ((err = gcry_cipher_encrypt(hd, enc_buff, in_len, s, in_len)) != 0) {
00095                 (void) fprintf(stderr, "gcry_cipher_encrypt failed:  %s/%s\n",
00096                                 gcry_strsource(err), gcry_strerror(err));
00097                 return 0;
00098         }
00099 
00100         ret_len = base64_encode_alloc(enc_buff, in_len, &ret);
00101 
00102         if (ret == NULL && ret_len == 0 && in_len != 0) {
00103                 free(enc_buff);
00104                 return NULL; /* input was too long */
00105         } else if (ret == NULL) {
00106                 free(enc_buff);
00107                 return NULL; /* couldn't allocate output buffer */
00108         }
00109 
00110         free(enc_buff);
00111 
00112         gcry_cipher_close(hd);
00113 
00114         return ret;
00115 }
00116 
00117 char *esapi_decrypt(struct esapi_ctx *ctx, const char *s) {
00118         gcry_error_t err = GPG_ERR_NO_ERROR;
00119         gcry_cipher_hd_t hd;
00120         size_t blk_len = 0;
00121         char *dec_buff = 0;
00122         char *ret;
00123         gcry_error_t key_len = 0;
00124         int ret_len = 0;
00125         size_t in_len = 0;
00126         bool dec_len = false;
00127 
00128         if ((ret = (char *) malloc(BUF_SIZE)) == 0) {
00129                 (void) fprintf(stderr, "malloc failure in %s\n", __func__);
00130                 exit(EXIT_FAILURE);
00131         }
00132 
00133         if ((err = gcry_cipher_open(&hd, ctx->sym_algo, ctx->sym_algo_mode, 0))
00134                         != 0) {
00135                 (void) fprintf(stderr, "gcry_cipher_open failed:  %s/%s\n",
00136                                 gcry_strsource(err), gcry_strerror(err));
00137                 return 0;
00138         }
00139 
00140         if ((key_len = gcry_cipher_get_algo_keylen(ctx->sym_algo)) == 0) {
00141                 (void) fprintf(stderr, "failed to get key length for %s in %s\n",
00142                                 gcry_cipher_algo_name(ctx->sym_algo), __func__);
00143                 return 0;
00144         }
00145 
00146         if ((blk_len = gcry_cipher_get_algo_blklen(ctx->sym_algo)) == 0) {
00147                 (void) fprintf(stderr, "failed to get block length for %s in %s\n",
00148                                 gcry_cipher_algo_name(ctx->sym_algo), __func__);
00149                 return 0;
00150         }
00151 
00152         if (ctx->sym_key[0] == '\0') {
00153                 (void) fprintf(stderr, "%s missing key\n", __func__);
00154                 return 0;
00155         }
00156 
00157         if ((err = gcry_cipher_setkey(hd, ctx->sym_key, key_len)) != 0) {
00158                 (void) fprintf(stderr, "gcry_cipher_setkey failed:  %s/%s\n",
00159                                 gcry_strsource(err), gcry_strerror(err));
00160                 return 0;
00161         }
00162 
00163         if (ctx->master_iv) {
00164                 if ((err = gcry_cipher_setiv(hd, ctx->master_iv, blk_len)) != 0) {
00165                         (void) fprintf(stderr, "gcry_cipher_setiv failed:  %s/%s\n",
00166                                         gcry_strsource(err), gcry_strerror(err));
00167                         return 0;
00168                 }
00169         }
00170 
00171         if ((dec_buff = gcry_xmalloc(BUF_SIZE)) == 0) {
00172                 (void) fprintf(stderr, "malloc failure in %s\n", __func__);
00173                 exit(EXIT_FAILURE);
00174         }
00175 
00176         in_len = BUF_SIZE;
00177 
00178         dec_len = base64_decode_alloc(s, strlen(s), &dec_buff, &in_len);
00179 
00180         if (dec_buff == false && ret_len == 0 && strlen(dec_buff) != 0) {
00181                 return NULL; /* input was too long */
00182         } else if (dec_buff == false) {
00183                 return NULL; /* couldn't allocate output buffer */
00184         }
00185 
00186         if ((ret = (char *) malloc(in_len)) == 0) {
00187                 (void) fprintf(stderr, "malloc failure in %s\n", __func__);
00188                 exit(EXIT_FAILURE);
00189         }
00190 
00191         if ((err = gcry_cipher_decrypt(hd, ret, in_len, dec_buff, in_len)) != 0) {
00192                 (void) fprintf(stderr, "gcry_cipher_decrypt failed:  %s/%s\n",
00193                                 gcry_strsource(err), gcry_strerror(err));
00194                 ret = 0;
00195         }
00196 
00197         return ret;
00198 }
00199 
00200 void esapi_crypto_init(struct esapi_ctx *ctx) {
00201 
00202         if (gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) {
00203                 fprintf(stderr, "GCRYPT has already been initialized\n");
00204         } else {
00205 
00206                 // Request FIPS 140-2 mode
00207                 if (ctx->fips140) {
00208                         gcry_control(GCRYCTL_FORCE_FIPS_MODE);
00209                 }
00210 
00211                 if (ctx->secure_mem) {
00212                         /* Version check should be the very first call because it
00213                          makes sure that important subsystems are initialized. */
00214                         if (!gcry_check_version(GCRYPT_VERSION)) {
00215                                 fputs("libgcrypt version mismatch\n", stderr);
00216                                 exit(EXIT_FAILURE);
00217                         }
00218 
00219                         /* We don't want to see any warnings, e.g. because we have not yet
00220                          parsed program options which might be used to suppress such
00221                          warnings. */
00222                         gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN);
00223 
00224                         /* ... If required, other initialization goes here.  Note that the
00225                          process might still be running with increased privileges and that
00226                          the secure memory has not been initialized.  */
00227 
00228                         /* Allocate a pool of 16k secure memory.  This make the secure memory
00229                          available and also drops privileges where needed.  */
00230                         gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0);
00231 
00232                         /* It is now okay to let Libgcrypt complain when there was/is
00233                          a problem with the secure memory. */
00234                         gcry_control(GCRYCTL_RESUME_SECMEM_WARN);
00235 
00236                         /* ... If required, other initialization goes here.  */
00237 
00238                 } else {
00239                         gcry_control(GCRYCTL_SET_VERBOSITY, (int) verbose);
00240 
00241                         if (!gcry_check_version(GCRYPT_VERSION)) {
00242                                 (void) fprintf(stderr, "GCRYPT version mismatch\n");
00243                                 exit(EXIT_FAILURE);
00244                         }
00245 
00246                         gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
00247 
00248                         gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
00249                 }
00250                 /* Tell Libgcrypt that initialization has completed. */
00251                 gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
00252         }
00253 }
00254 
00255 char *esapi_hash(struct esapi_ctx *ctx, const char *s) {
00256         int len;
00257         void *digest;
00258         char *ret = 0;
00259         int ret_len = 0;
00260 
00261         len = gcry_md_get_algo_dlen(ctx->hash_algo);
00262 
00263         if ((digest = malloc(len)) == 0) {
00264                 (void) fprintf(stderr, "malloc failure in %s\n", __func__);
00265                 exit(EXIT_FAILURE);
00266         }
00267 
00268         gcry_md_hash_buffer(ctx->hash_algo, digest, s, strlen(s));
00269 
00270         ret_len = base64_encode_alloc(digest, len, &ret);
00271 
00272         if (ret == NULL && ret_len == 0 && len != 0) {
00273                 free(digest);
00274                 return NULL; /* input was too long */
00275         } else if (ret == NULL) {
00276                 free(digest);
00277                 return NULL; /* couldn't allocate output buffer */
00278         }
00279 
00280         free(digest);
00281 
00282         return ret;
00283 }
00284 
00285 void esapi_fill_crypto_key(struct esapi_ctx *ctx, char *buff, int len) {
00286         gcry_random_level_t level = GCRY_VERY_STRONG_RANDOM;
00287         int i;
00288 
00289         gcry_randomize(buff, len, level);
00290 
00291         for (i = 0; i < len; i++) {
00292                 buff[i] = esapi_alphabet[(buff[i] % strlen(esapi_alphabet) - 1)];
00293         }
00294 }
00295 
00296 void esapi_fill_random_token(struct esapi_ctx *ctx, char *buff, int len) {
00297         gcry_random_level_t level = GCRY_STRONG_RANDOM;
00298         int i;
00299 
00300         gcry_randomize(buff, len, level);
00301 
00302         for (i = 0; i < len; i++) {
00303                 buff[i] = esapi_alphabet[(buff[i] % strlen(esapi_alphabet) - 1)];
00304         }
00305 }
00306 
00310 gcry_sexp_t *esapi_sign(struct esapi_ctx *ctx, void *msg, int len) {
00311         gcry_sexp_t *sig;
00312         static gcry_sexp_t data;
00313         gcry_error_t err;
00314         static gcry_sexp_t priv_key;
00315 
00316         err = gcry_sexp_new(&data, msg, len, 0);
00317 
00318         if (err) {
00319                 (void) fprintf(stderr, "gcry_sexp_new failed:  %s/%s\n",
00320                                 gcry_strsource(err), gcry_strerror(err));
00321                 return 0;
00322         }
00323 
00324         if ((sig = (gcry_sexp_t *) malloc(sizeof(gcry_sexp_t))) == 0) {
00325                 (void) fprintf(stderr, "malloc failure in %s\n", __func__);
00326                 exit(EXIT_FAILURE);
00327         }
00328 
00329         priv_key = convert_to_asymmetric_key(ctx->asym_priv_key, 0);
00330 
00331         err = gcry_pk_sign(sig, data, priv_key);
00332 
00333         if (err) {
00334                 free(sig);
00335                 return 0;
00336         }
00337 
00338         return sig;
00339 }
00340 
00344 gcry_sexp_t convert_to_asymmetric_key(void *buff, int key_len) {
00345         gcry_sexp_t empty = 0;
00346         return empty;
00347 }
00348 
00354 int esapi_verify_signature(struct esapi_ctx *ctx, void *msg, int m_len,
00355                 gcry_sexp_t *sig) {
00356         gcry_error_t err;
00357         gcry_sexp_t data; // have to turn msg + len into this object
00358         gcry_sexp_t priv_key; // have to turn ctx->asym_priv_key into this
00359         err = gcry_pk_verify(*sig, data, priv_key);
00360 
00361         return (err == 0) ? 0 : -1;
00362 }
00363 
00369 char *encrypt_and_sign(struct esapi_ctx *ctx, void *msg, int len) {
00370         return NULL;
00371 }
00372 
00378 char *decrypt_and_verify(struct esapi_ctx *ctx, void *msg, int len) {
00379         return NULL;
00380 }
 All Data Structures Files Functions Variables Typedefs Defines