static int w_crypto_aes_decrypt(sip_msg_t* msg, char* inb, char* keyb, char* outb) { str ins; str keys; pv_spec_t *dst; pv_value_t val; EVP_CIPHER_CTX *de=NULL; str etext; if (fixup_get_svalue(msg, (gparam_t*)inb, &ins) != 0) { LM_ERR("cannot get input value\n"); return -1; } if (fixup_get_svalue(msg, (gparam_t*)keyb, &keys) != 0) { LM_ERR("cannot get key value\n"); return -1; } de = EVP_CIPHER_CTX_new(); if(de==NULL) { LM_ERR("cannot get new cipher context\n"); return -1; } dst = (pv_spec_t*)outb; /* gen key and iv. init the cipher ctx object */ if (crypto_aes_init((unsigned char *)keys.s, keys.len, (unsigned char*)((_crypto_salt_param)?_crypto_salt:0), NULL, de)) { EVP_CIPHER_CTX_free(de); LM_ERR("couldn't initialize AES cipher\n"); return -1; } memset(&val, 0, sizeof(pv_value_t)); etext.s = pv_get_buffer(); etext.len = base64_dec((unsigned char *)ins.s, ins.len, (unsigned char *)etext.s, pv_get_buffer_size()-1); if (etext.len < 0) { EVP_CIPHER_CTX_free(de); LM_ERR("base64 inpuy with encrypted value is too large (need %d)\n", -etext.len); return -1; } val.rs.len = etext.len; val.rs.s = (char *)crypto_aes_decrypt(de, (unsigned char *)etext.s, &val.rs.len); if(val.rs.s==NULL) { EVP_CIPHER_CTX_free(de); LM_ERR("AES decryption failed\n"); return -1; } LM_DBG("plain result: [%.*s]\n", val.rs.len, val.rs.s); val.flags = PV_VAL_STR; dst->setf(msg, &dst->pvp, (int)EQ_T, &val); free(val.rs.s); EVP_CIPHER_CTX_cleanup(de); EVP_CIPHER_CTX_free(de); return 1; }
/** * testing function */ int crypto_aes_test(void) { /* "opaque" encryption, decryption ctx structures * that libcrypto uses to record status of enc/dec operations */ EVP_CIPHER_CTX en, de; /* The salt paramter is used as a salt in the derivation: * it should point to an 8 byte buffer or NULL if no salt is used. */ unsigned char salt[] = {1,2,3,4,5,6,7,8}; unsigned char *key_data; int key_data_len, i; char *input[] = {"Kamailio - The Open Source SIP Server", "Thank you for flying Kamailio!", "100 Trying\nYour call is important to us", NULL }; /* the key_data for testing */ key_data = (unsigned char *)"kamailio-sip-server"; key_data_len = strlen((const char *)key_data); /* gen key and iv. init the cipher ctx object */ if (crypto_aes_init(key_data, key_data_len, salt, &en, &de)) { LM_ERR("couldn't initialize AES cipher\n"); return -1; } /* encrypt and decrypt each input string and compare with the original */ for (i = 0; input[i]; i++) { char *plaintext; unsigned char *ciphertext; int olen, len; /* The enc/dec functions deal with binary data and not C strings. * strlen() will return length of the string without counting the '\0' * string marker. We always pass in the marker byte to the * encrypt/decrypt functions so that after decryption we end up with * a legal C string */ olen = len = strlen(input[i])+1; ciphertext = crypto_aes_encrypt(&en, (unsigned char *)input[i], &len); plaintext = (char *)crypto_aes_decrypt(&de, ciphertext, &len); if (strncmp(plaintext, input[i], olen)) LM_ERR("FAIL: enc/dec failed for \"%s\"\n", input[i]); else LM_NOTICE("OK: enc/dec ok for \"%s\"\n", plaintext); free(ciphertext); free(plaintext); } EVP_CIPHER_CTX_cleanup(&de); EVP_CIPHER_CTX_cleanup(&en); return 0; }