bool MCCrypt_random_bytes(uint32_t p_bytecount, void *&r_bytes) { bool t_success = true; unsigned char *t_bytes = nil; t_success = InitSSLCrypt() == True; if (t_success) t_success = MCMemoryAllocate(p_bytecount, t_bytes); if (t_success) t_success = RAND_bytes(t_bytes, p_bytecount) == 1; if (t_success) r_bytes = t_bytes; return t_success; }
void MCSecurityEvalRandomBytes(MCExecContext& ctxt, uinteger_t p_byte_count, MCDataRef& r_bytes) { if (!InitSSLCrypt()) { ctxt.LegacyThrow(EE_SECURITY_NOLIBRARY); return; } if (MCSRandomData (p_byte_count, r_bytes)) { ctxt.SetTheResultToEmpty(); return; } ctxt.SetTheResultToCString("error: could not get random bytes"); }
void SSL_ciphernames(MCExecPoint &ep) { #ifdef MCSSL // MW-2004-12-29: Integrate Tuviah's fixes static char sslcipherlist[] = "bf,128\nbf-cbc,128\nbf-cfb,128\nbf-ecb,128\nbf-ofb,128\nblowfish,128\ncast,128\ncast-cbc,128\ncast5-cbc,128\ncast5-cfb,128\ncast5-ecb,128\ncast5-ofb,128\ndes,64\ndes-cbc,64\ndes-cfb,64\ndes-ecb,64\ndes-ede,128\ndes-ede-cbc,128\ndes-ede-cfb,128\ndes-ede-ofb,128\ndes-ede3,192\ndes-ede3-cbc,192\ndes-ede3-cfb,192\ndes-ede3-ofb,192\ndes-ofb,64\ndes3,192\ndesx,192\ndesx-cbc,192\nrc2,128\nrc2-40-cbc,40\nrc2-64-cbc,64\nrc2-cbc,128\nrc2-cfb,128\nrc2-ecb,128\nrc2-ofb,128\nrc4,128\nrc4-40,40\nrc5,128\nrc5-cbc,128\nrc5-cfb,128\nrc5-ecb,128\nrc5-ofb,128"; isfirstcipher = True; ep.clear(); if (!InitSSLCrypt()) { char sslerrbuf[256]; SSLError(sslerrbuf); MCresult->copysvalue(sslerrbuf); } else OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, list_ciphers_cb, &ep); #else // MW-2013-01-15: [[ Bug 10631 ]] Make sure we clear the return value if no // SSL! ep . clear(); #endif }
//error buf should have a buffer of at least 256 bytes. unsigned long SSLError(char *errbuf) { if (!InitSSLCrypt()) { strcpy(errbuf,"ssl library not found"); return 0; } #ifdef MCSSL unsigned long ecode = ERR_get_error(); if (errbuf) { if (ecode) ERR_error_string_n(ecode,errbuf,255); else errbuf[0] = '\0'; } return ecode; #else return 0; #endif }
Exec_stat MCIdeSign::exec(MCExecPoint& ep) { Exec_stat t_stat; t_stat = ES_NORMAL; // Clear the result as we return an error there MCresult -> clear(); if (t_stat == ES_NORMAL) t_stat = m_params -> eval(ep); MCVariableValue *t_array; if (t_stat == ES_NORMAL) { t_array = ep . getarray(); if (t_array == NULL) return ES_ERROR; } MCExecPoint ep2(ep); MCDeploySignParameters t_params; memset(&t_params, 0, sizeof(MCDeploySignParameters)); if (t_stat == ES_NORMAL) t_stat = fetch_opt_cstring(ep2, t_array, "passphrase", t_params . passphrase); if (t_stat == ES_NORMAL) t_stat = fetch_opt_filepath(ep2, t_array, "certificate", t_params . certificate); if (t_stat == ES_NORMAL) t_stat = fetch_opt_filepath(ep2, t_array, "privatekey", t_params . privatekey); if (t_stat == ES_NORMAL) t_stat = fetch_opt_filepath(ep2, t_array, "certstore", t_params . certstore); if (t_stat == ES_NORMAL) t_stat = fetch_opt_cstring(ep2, t_array, "timestamper", t_params . timestamper); if (t_stat == ES_NORMAL) t_stat = fetch_opt_cstring(ep2, t_array, "description", t_params . description); if (t_stat == ES_NORMAL) t_stat = fetch_opt_cstring(ep2, t_array, "url", t_params . url); if (t_stat == ES_NORMAL) t_stat = fetch_filepath(ep2, t_array, "input", t_params . input); if (t_stat == ES_NORMAL) t_stat = fetch_filepath(ep2, t_array, "output", t_params . output); if (t_stat == ES_NORMAL) if (t_params . certstore != NULL && (t_params . certificate != NULL || t_params . privatekey != NULL)) t_stat = ES_ERROR; if (t_stat == ES_NORMAL) if (t_params . certstore == NULL && (t_params . certificate == NULL || t_params . privatekey == NULL)) t_stat = ES_ERROR; bool t_can_sign; t_can_sign = true; if (t_stat == ES_NORMAL && !InitSSLCrypt()) { MCresult -> sets("could not initialize SSL"); t_can_sign = false; } if (t_can_sign && t_stat == ES_NORMAL) { if (m_platform == PLATFORM_WINDOWS) MCDeploySignWindows(t_params); MCDeployError t_error; t_error = MCDeployCatch(); if (t_error != kMCDeployErrorNone) MCresult -> sets(MCDeployErrorToString(t_error)); } delete t_params . passphrase; delete t_params . certificate; delete t_params . privatekey; delete t_params . certstore; delete t_params . timestamper; delete t_params . description; delete t_params . url; delete t_params . input; delete t_params . output; return t_stat; }
char *SSL_encode(Boolean isdecrypt, char *ciphername, const char *data, uint4 inlen,uint4 &outlen, //data to decrypt, length of that data, and pointer to descypted data length const char *keystr, int4 keystrlen, Boolean ispassword, uint2 keylen, const char *saltstr, uint2 saltlen, const char *ivstr, uint2 ivlen) { //password or key, optional key length if (!InitSSLCrypt()) return NULL; #ifdef MCSSL // MW-2011-05-24: [[ Bug 9536 ]] The key length is a function of 'keylen' and for some ciphers // can be larger than 32 bytes. For now, increase the buffer to 256 bytes given a maximum // theoretical key length of 2048. uint1 iv[EVP_MAX_IV_LENGTH], key[256]; if (keylen > 2048) return NULL; const EVP_CIPHER *cipher=EVP_get_cipherbyname(ciphername); uint1 operation = isdecrypt ? 0: 1; //get cipher object if (!cipher) { outlen = 789; return NULL; } static const char magic[]="Salted__"; int4 res = 0; //set up cipher context EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); //init context with cipher and specify operation if (EVP_CipherInit(&ctx, cipher,NULL, NULL, operation) == 0) return NULL; //try setting keylength if specified. This will fail for some ciphers. if (keylen && EVP_CIPHER_CTX_set_key_length(&ctx, keylen/8) == 0) return NULL; //get new keylength in bytes int4 curkeylength = EVP_CIPHER_CTX_key_length(&ctx); //zero key and iv memset(key,0,EVP_MAX_KEY_LENGTH); memset(iv,0,EVP_MAX_IV_LENGTH); //if password combine with salt value to generate key unsigned char saltbuf[PKCS5_SALT_LEN]; memset(saltbuf,0,sizeof(saltbuf)); char *tend = (char *)data + inlen; // MW-2004-12-02: Fix bug 2411 - a NULL salt should result in a random one being // generated, if saltstr is NULL and saltlen is zero then the salt should // be taken as being the empty string. if (ispassword) { if (saltstr == NULL) RAND_bytes(saltbuf, sizeof(saltbuf)); else memcpy(saltbuf,saltstr,MCU_min(saltlen,PKCS5_SALT_LEN)); // MW-2004-12-02: We should only do this if we are decrypting if (isdecrypt && inlen > sizeof(magic) && memcmp(data,magic,sizeof(magic)-1) == 0) { data += sizeof(magic) - 1; if (saltstr == NULL || saltlen == 0) memcpy(saltbuf,data,sizeof(saltbuf)); data += sizeof(saltbuf); } curkeylength = EVP_BytesToKey(cipher,EVP_md5(),(const unsigned char *)saltbuf,(unsigned char *)keystr, keystrlen,1,key,iv); } else {//otherwise copy to key if (keystrlen != curkeylength) { //sanity check then passed wrong size for key outlen = 790; return NULL; } else memcpy(key,keystr,curkeylength); } if (ivstr != NULL && ivlen > 0) { memset(iv,0,EVP_MAX_IV_LENGTH); memcpy(iv,ivstr,MCU_min(ivlen,EVP_MAX_IV_LENGTH)); } if (EVP_CipherInit(&ctx, NULL, key, iv, operation) == 0) return NULL; int4 tmp, ol; ol = 0; //allocate memory to hold encrypted/decrypted data + an extra block + null terminator for block ciphers. unsigned char *outdata = (unsigned char *)malloc(inlen + EVP_CIPHER_CTX_block_size(&ctx) + 1 + sizeof(magic) + sizeof(saltbuf)); //do encryption/decryption if (outdata == NULL) { outlen = 791; return NULL; } // MW-2004-12-02: Only prepend the salt if we generated the key (i.e. password mode) if (!isdecrypt && ispassword) { memcpy(&outdata[ol],magic,sizeof(magic)-1); ol += sizeof(magic)-1; memcpy(&outdata[ol],saltbuf,sizeof(saltbuf)); ol += sizeof(saltbuf); } // MW-2007-02-13: [[Bug 4258]] - SSL now fails an assertion if datalen == 0 if (tend - data > 0) { if (EVP_CipherUpdate(&ctx,&outdata[ol],&tmp,(unsigned char *)data,tend-data) == 0) { delete outdata; return NULL; } ol += tmp; } //for padding if (EVP_CipherFinal(&ctx,&outdata[ol],&tmp) == 0) { delete outdata; return NULL; } outlen = ol + tmp; //cleam up context and return data EVP_CIPHER_CTX_cleanup(&ctx); outdata[outlen] = 0; //null terminate data return (char *)outdata; #else return NULL; #endif }
bool MCCrypt_rsa_op(bool p_encrypt, RSA_KEYTYPE p_key_type, const char *p_message_in, uint32_t p_message_in_length, const char *p_key, uint32_t p_key_length, const char *p_passphrase, char *&r_message_out, uint32_t &r_message_out_length, char *&r_result, uint32_t &r_error) { bool t_success = true; EVP_PKEY *t_key = NULL; RSA *t_rsa = NULL; int32_t t_rsa_size; uint8_t *t_output_buffer = NULL; int32_t t_output_length; if (!InitSSLCrypt()) { t_success = false; MCCStringClone("error: ssl library initialization failed", r_result); } if (t_success) { if (!load_pem_key(p_key, p_key_length, p_key_type, p_passphrase, t_key)) { t_success = false; MCCStringClone("error: invalid key", r_result); } } if (t_success) { t_rsa = EVP_PKEY_get1_RSA(t_key); if (t_rsa == NULL) { t_success = false; MCCStringClone("error: not an RSA key", r_result); } } if (t_success) { t_rsa_size = RSA_size(t_rsa); if (!MCMemoryAllocate(t_rsa_size, t_output_buffer)) { t_success = false; r_error = EE_NO_MEMORY; } } int (*t_rsa_func)(int, const unsigned char*, unsigned char*, RSA*, int) = NULL; if (t_success) { if (p_encrypt) { if (p_key_type == RSAKEY_PRIVKEY) t_rsa_func = RSA_private_encrypt; else t_rsa_func = RSA_public_encrypt; if (p_message_in_length >= unsigned(t_rsa_size - 11)) { t_success = false; MCCStringClone("error: message too large", r_result); } } else { if (p_key_type == RSAKEY_PRIVKEY) t_rsa_func = RSA_private_decrypt; else t_rsa_func = RSA_public_decrypt; if (p_message_in_length != t_rsa_size) { t_success = false; MCCStringClone("error: invalid message size", r_result); } } } if (t_success) { t_output_length = t_rsa_func(p_message_in_length, (const uint8_t*)p_message_in, t_output_buffer, t_rsa, RSA_PKCS1_PADDING); if (t_output_length < 0) { t_success = false; MCCStringClone("error: SSL operation failed", r_result); } } if (t_rsa != NULL) RSA_free(t_rsa); if (t_key != NULL) EVP_PKEY_free(t_key); if (t_success) { r_message_out = (char*)t_output_buffer; r_message_out_length = t_output_length; } else { uint32_t t_err; t_err = ERR_get_error(); if (t_err) { const char *t_ssl_error = ERR_reason_error_string(t_err); MCCStringAppendFormat(r_result, " (SSL error: %s)", t_ssl_error); } MCMemoryDeallocate(t_output_buffer); } return t_success; }