ESAPI-C 1.0
The OWASP Enterprise Security API for C
|
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 }