void SSL_Cipher::DecryptVector(const SSL_varvector32 &source, SSL_varvector32 &target) { uint32 len,len1,len2; byte *target1; len = source.GetLength(); target.Resize(len+2*InputBlockSize()); if(InputBlockSize() == 0) { RaiseAlert(SSL_Fatal, SSL_InternalError); target.RaiseAlert(this); } if(target.ErrorRaisedFlag) { target.Resize(0); return; } target1 = target.GetDirect(); InitDecrypt(); target1 = Decrypt(source.GetDirect(),len,target1,len1, target.GetLength()); FinishDecrypt(target1,len2, target.GetLength()- len1); len1+= len2; target.Resize(len1); }
void SSL_Version_Dependent::AddHandshakeHash(SSL_secure_varvector32 *source) { if(!source) return; SSL_secure_varvector32 *temp = OP_NEW(SSL_secure_varvector32, ()); if(temp) { temp->ForwardTo(this); temp->Set(source); if(!temp->Error()) temp->Into(&handshake_queue); else OP_DELETE(temp); } else RaiseAlert(SSL_Internal,SSL_Allocation_Failure); if(final_hash->HashID() != SSL_NoHash) final_hash->CalculateHash(*source); #if defined _DEBUG && defined YNP_WORK handshake.Append(*source); #endif }
void SSL_Cipher::EncryptVector(const SSL_varvector32 &source, SSL_varvector32 &target) { uint32 len,size; byte *target1; len = source.GetLength(); size = Calc_BufferSize(len+(GetPaddingStrategy() != SSL_NO_PADDING && CipherType() == SSL_BlockCipher ? 1 : 0)); target.Resize(size); if(size==0) { RaiseAlert(SSL_Fatal, SSL_InternalError); target.RaiseAlert(this); } if(target.ErrorRaisedFlag) { target.Resize(0); return; } target1 = target.GetDirect(); InitEncrypt(); target1 = Encrypt(source.GetDirect(),len,target1,size, target.GetLength()); FinishEncrypt(target1,size, target.GetLength()- size); }
SSL_Handshake_Action SSL_Version_Dependent::HandleHandshakeMessage(SSL_HandShakeType mtyp) { Handshake_actions_st *action = (Handshake_actions_st *) Receive_Queue.First(); while(action) { if(action->msg_type == mtyp) { if(action->msg_status == Handshake_Expected || action->msg_status == Handshake_MustReceive) { action->msg_status = Handshake_Received; return action->action; } else if(action->msg_status == Handshake_Ignore) return action->action; // Dont bother, but return action break; // else unexpected message } else if(action->msg_status == Handshake_MustReceive) break; // unexpected message action = (Handshake_actions_st *) action->Suc(); } RaiseAlert(SSL_Fatal, SSL_Unexpected_Message); return Handshake_Handle_Error; }
uint32 SSL_Record_Layer::Handle_Receive_Record(const byte *source, uint32 length) { SSL_Alert err; if (length == 0 || source == NULL) return 0; if(connstate->version_specific == NULL) { RaiseAlert(SSL_Fatal, SSL_Unexpected_Message); return length; } #ifdef LIBSSL_HANDSHAKE_HEXDUMP if(g_selftest.running) { if(!statusinfo.ApplicationActive) { SSL_secure_varvector32 *data = OP_NEW(SSL_secure_varvector32, ()); if(data) { data->SetTag(1); // Receive data->Set((unsigned char *)source, length); data->Into(&pending_connstate->selftest_sequence); } } else
void RaiseEntryAlert( const char *alert_name, /* alert name (if set) */ const char *alert_string, /* alert description */ const char *entry_path, /* entry path */ const char *entry_info) /* alert related attributes */ { char title[1024]; /* lockless check (not a big problem if some alerts are sent without * being batched). */ if ( alert_batching ) { if ( alert_name && !EMPTY_STRING(alert_name) ) strcpy(title, alert_name ); else { if ( snprintf(title, 1024, "unnamed alert %s", alert_string ) > 80 ) { /* truncate at 80 char: */ strcpy( title+77, "..." ); } } Alert_Add( title, entry_path, entry_info ); } else { if ( alert_name && !EMPTY_STRING(alert_name) ) snprintf(title, 1024, "Robinhood alert (%s on %s): %s", global_config.fs_path, machine_name, alert_name ); else snprintf(title, 1024, "Robinhood alert (%s on %s): entry matches alert rule", global_config.fs_path, machine_name ); if ( log_config.alert_show_attrs ) RaiseAlert( title, "Entry: %s\nAlert condition: %s\n" "Entry info:\n%s", entry_path, alert_string, entry_info ); else RaiseAlert( title, "Entry: %s\nAlert condition: %s\n", entry_path, alert_string ); } }
void SSL_HandShakeMessage::PerformActionL(DataStream::DatastreamAction action, uint32 arg1, uint32 arg2) { switch(action) { case DataStream::KReadAction: case DataStream::KWriteAction: { uint32 step = arg1; int record_item_id = (int) arg2; if(record_item_id == DataStream_SequenceBase::STRUCTURE_START) { if(action == DataStream::KWriteAction) spec.enable_length = (connstate->version.Major() >= 3); else length.SetEnableRecord(connstate->version.Major() >= 3); dummy.ResetRecord(); dummy.SetEnableRecord(TRUE); } LoadAndWritableList::PerformActionL(action, step, record_item_id); if(action == DataStream::KReadAction) { if(record_item_id == RECORD_TAG) { if(connstate->version.Major() < 3) SetTag((SSL_HandShakeType)(((uint32) GetTag()) | 0x100)); // Convert 8 bit value into the SSL v2 message type LEAVE_IF_ERROR(SetMessage((SSL_HandShakeType) GetTag())); } else if(record_item_id == STRUCTURE_FINISHED) { if(dummy.GetLength() != 0 && GetTag() != SSL_Client_Hello) RaiseAlert(SSL_Fatal,SSL_Illegal_Parameter); } } } break; default: LoadAndWritableList::PerformActionL(action, arg1, arg2); } }
void SSL_Error_Status::RaiseAlert(OP_STATUS op_err) { SSL_AlertLevel lev=SSL_Internal; SSL_AlertDescription des = SSL_InternalError; switch(op_err) { case OpStatus::ERR_NO_MEMORY: des = SSL_Allocation_Failure; break; case OpRecStatus::RECORD_TOO_SHORT: des = SSL_Decode_Error; lev = SSL_Fatal; break; } RaiseAlert(lev, des); }
void SSL_Version_Dependent::AddHandshakeAction(Handshake_Queue action_queue, SSL_V3_handshake_id id, SSL_HandShakeType mtyp, SSL_Handshake_Status _mstat, SSL_Handshake_Action actn, Handshake_Add_Point add_policy, SSL_V3_handshake_id add_id) { Head *target = (action_queue == Handshake_Receive ? &Receive_Queue : &Send_Queue); Handshake_actions_st *item = OP_NEW(Handshake_actions_st, (id, mtyp, _mstat, actn)); if(item == NULL) { RaiseAlert(SSL_Internal, SSL_Allocation_Failure); return; } switch(add_policy) { case Handshake_Add_In_Front: item->IntoStart(target); break; case Handshake_Add_Before_ID: case Handshake_Add_After_ID: { Handshake_actions_st *action = GetHandshakeItem( action_queue, add_id); if(action) { if(add_policy == Handshake_Add_Before_ID) item->Precede(action); else item->Follow(action); break; } // else use default action } case Handshake_Add_At_End: default: item->Into(target); break; } }
OP_STATUS SSL_HandShakeMessage::SetMessage( SSL_HandShakeType item) { if ((SSL_HandShakeType) GetTag() != item || msg == NULL) { LoadAndWritableList *temp; if(msg != NULL) { temp = msg; msg = NULL; ServerKeys = NULL; OP_DELETE(temp); } temp = NULL; switch (item) { case SSL_Client_Hello : temp = OP_NEW(SSL_Client_Hello_st, ()); break; case SSL_Server_Hello : temp = OP_NEW(SSL_Server_Hello_st, ()); break; case SSL_Certificate : temp = OP_NEW(SSL_Certificate_st, ()); break; case SSL_Server_Key_Exchange : temp = ServerKeys = OP_NEW(SSL_Server_Key_Exchange_st, ()); break; case SSL_CertificateRequest : temp = CertRequest = OP_NEW(SSL_CertificateRequest_st, ()); break; case SSL_Certificate_Verify : temp = OP_NEW(SSL_CertificateVerify_st, ()); break; case SSL_Client_Key_Exchange : temp = OP_NEW(SSL_Client_Key_Exchange_st, ()); break; case SSL_Finished : temp = OP_NEW(SSL_Finished_st, ()); break; case SSL_Server_Hello_Done : temp = OP_NEW(SSL_Hello_Done_st, ()); break; case TLS_NextProtocol : temp = OP_NEW(SSL_NextProtocol_st, ()); break; #ifndef TLS_NO_CERTSTATUS_EXTENSION case TLS_CertificateStatus: temp = OP_NEW(TLS_CertificateStatusResponse, ()); break; #endif default : break; } msg = temp; if(msg == NULL && (item != SSL_NONE && item != SSL_Server_Hello_Done && item != SSL_Hello_Request)) { RaiseAlert(SSL_Internal, SSL_Allocation_Failure); return OpStatus::ERR_NO_MEMORY; } SetTag(item); if(connstate != NULL) { if(item == SSL_Server_Key_Exchange) ServerKeys->SetCommState(connstate); else if(item == SSL_CertificateRequest) CertRequest->SetCommState(connstate); } dummy.ResetRecord(); }
void SSL_Error_Status::RaiseAlert(const SSL_Error_Status_Base *other) { RaiseAlert((SSL_Error_Status *) other); }
SSL_CertificateVerifier::SSL_CertificateVerifier(int dialog): warncount(0), warnstatus(NULL), warn_mask(0), #ifdef LIBSSL_ENABLE_CRL_SUPPORT loaded_crls(FALSE), #endif url_loading_mode(Loading_None), pending_url(NULL), block_ica_requests(FALSE), #ifdef LIBSSL_AUTO_UPDATE_ROOTS block_retrieve_requests(FALSE), auto_fetcher(MSG_SSL_AUTOFETCH_FINISHED, (UINTPTR) this), ignore_repository(FALSE), #endif accept_unknown_ca(FALSE), verify_state(Verify_NotStarted), doing_iteration(FALSE), port(0), certificate_purpose(SSL_Purpose_Server_Certificate), accept_search_mode(SSL_CONFIRMED), dialog_type(dialog), cert_handler(NULL), batch_request(NULL), #ifndef TLS_NO_CERTSTATUS_EXTENSION ocsp_extensions_sent(FALSE), certificate_checked_for_ocsp(FALSE), certificate_loading_ocsp(FALSE), #endif check_name(FALSE), certificate_status(SSL_CERT_NO_WARN), UserConfirmed(NO_INTERACTION), security_rating(SECURITY_STATE_UNKNOWN), low_security_reason(SECURITY_REASON_NOT_NEEDED), val_certificate_count(0), #ifdef SSL_CHECK_EXT_VALIDATION_POLICY check_extended_validation(TRUE), extended_validation(FALSE), disable_EV(FALSE), #endif show_dialog(TRUE), window(NULL) { Certificate.ForwardTo(this); #ifndef TLS_NO_CERTSTATUS_EXTENSION Validated_Certificate.ForwardTo(this); sent_ocsp_extensions.ForwardTo(this); received_ocsp_response.ForwardTo(this); #endif #ifdef LIBSSL_AUTO_UPDATE_ROOTS static const OpMessage messages[] = { MSG_DO_AUTO_ROOT_REQUEST, MSG_DO_AUTO_UNTRUSTED_REQUEST }; OP_STATUS op_err = g_main_message_handler->SetCallBackList(&auto_fetcher, 0, messages, ARRAY_SIZE(messages)); if(OpStatus::IsError(op_err)) RaiseAlert(op_err); if(!g_ssl_api->CheckSecurityManager()) RaiseAlert(OpStatus::ERR_NO_MEMORY); #endif if(!g_ssl_api->CheckSecurityManager()) RaiseAlert(OpStatus::ERR_NO_MEMORY); }
SSL_Record_Base *SSL_Record_Base::Encrypt(SSL_CipherSpec *cipher) { uint32 blocksize; if(cipher == NULL || (blocksize = cipher->Method->InputBlockSize()) == 0) { RaiseAlert(SSL_Fatal, SSL_InternalError); return NULL; } OpStackAutoPtr<SSL_Record_Base> encrypt_target(InitEncryptTarget()); if(ErrorRaisedFlag) return NULL; LoadAndWritableList crypt_source; SSL_secure_varvector32 IV; SSL_secure_varvector16 payload_data; SSL_secure_varvector16 MAC_data; SSL_secure_varvector16 pad_data; crypt_source.ForwardTo(this); if(encrypt_target->IV_field && blocksize > 1) { crypt_source.AddItem(&IV); // Keep the IV from the previous record (option 2b from RFC 4346) IV.SetEnableRecord(TRUE); IV.FixedLoadLength(TRUE); SSL_RND(IV, blocksize); } crypt_source.AddItem(&payload_data); payload_data.SetExternal(GetDirect()); payload_data.Resize(GetLength()); payload_data.FixedLoadLength(TRUE); crypt_source.AddItem(&MAC_data); MAC_data.Resize(cipher->MAC->Size()); MAC_data.FixedLoadLength(TRUE); if(ErrorRaisedFlag) return NULL; if(blocksize > 1) { uint16 plen = payload_data.GetLength() + MAC_data.GetLength(); uint16 elen = cipher->Method->Calc_BufferSize(plen); uint16 paddinglength = (elen-plen); if(paddinglength == 0) paddinglength = blocksize; uint8 pad_char = (uint8) (paddinglength-1); crypt_source.AddItem(&pad_data); pad_data.Resize(paddinglength); pad_data.Blank(pad_char); pad_data.FixedLoadLength(TRUE); } { SSL_ContentType r_type; SSL_ProtocolVersion r_ver; r_type = GetType(); r_ver = GetVersion(); encrypt_target->SetType(r_type); encrypt_target->SetVersion(r_ver); if(MAC_data.GetLength()) { SSL_TRAP_AND_RAISE_ERROR_THIS(cipher->MAC->CalculateRecordMAC_L(cipher->Sequence_number, r_ver, r_type, payload_data,pad_data.GetDirect(), pad_data.GetLength(), MAC_data)); } } SSL_secure_varvector16 tempdata; SSL_TRAP_AND_RAISE_ERROR_THIS(crypt_source.WriteRecordL(&tempdata)); if(ErrorRaisedFlag) return NULL; cipher->Method->EncryptVector(tempdata, *encrypt_target); cipher->Sequence_number++; if(ErrorRaisedFlag || cipher->Method->Error()) return NULL; return encrypt_target.release(); }
SSL_Record_Base *SSL_Record_Base::Decrypt(SSL_CipherSpec *cipher) { uint16 blocksize; if(cipher == NULL || (blocksize = cipher->Method->InputBlockSize()) == 0) { RaiseAlert(SSL_Fatal, SSL_InternalError); return NULL; } SSL_secure_varvector16 tempdata; tempdata.ForwardTo(this); UINT mac_hash_size = cipher->MAC->Size(); // Counter measure for paper "Lucky Thirteen: Breaking the TLS and DTLS Record Protocols" // Sanity check the cipher text length. // Lucky Thirteen step 1 if(blocksize > 1) { UINT mimmimum_cipher_length = MAX(blocksize, mac_hash_size + 1); if (IV_field) mimmimum_cipher_length += blocksize; if (GetLength() < mimmimum_cipher_length) { RaiseAlert(SSL_Fatal, SSL_Decryption_Failed); return NULL; } } cipher->Method->DecryptVector(*this, tempdata); if(ErrorRaisedFlag || cipher->Method->Error()) return NULL; #ifdef TST_DUMP DumpTofile(tempdata, tempdata.GetLength() ,"Decrypt outputdata (includes padding): ","sslcrypt.txt"); #endif OP_MEMORY_VAR uint16 plainlength = tempdata.GetLength(); // The padding length byte as given in the stream UINT8 padlen = 0; OP_MEMORY_VAR uint16 paddinglength = 0; const byte * OP_MEMORY_VAR source = tempdata.GetDirect(); { BOOL length_OK = TRUE; if(blocksize == 1) { if(plainlength != GetLength()) length_OK = FALSE; } else// if(blocksize != 1) { if(plainlength % blocksize != 0) length_OK = FALSE; else if(IV_field) { if(plainlength < blocksize) length_OK = FALSE; } } if(!length_OK) { RaiseAlert(SSL_Fatal, SSL_Decryption_Failed); return NULL; } } if(IV_field && blocksize > 1) { plainlength -= blocksize; source += blocksize; } int original_plainlength = plainlength; OpStackAutoPtr<SSL_Record_Base> decrypt_target(InitDecryptTarget(cipher)); if(ErrorRaisedFlag) return NULL; OP_MEMORY_VAR BOOL padding_failure = FALSE; if(blocksize > 1) { if(plainlength == 0) { RaiseAlert(SSL_Fatal, SSL_Illegal_Parameter); return NULL; } padlen = source[plainlength-1]; paddinglength = padlen + 1; // Lucky Thirteen counter measure step 3 if (mac_hash_size + padlen + 1 > plainlength) { for(UINT16 i = 0;i < 256; i++) { // Dummy check, to avoid timing differences. if(source[i] != padlen ) //dummy check padding_failure = TRUE; } padding_failure = TRUE; paddinglength = 0; } else if(version >= SSL_ProtocolVersion(3,2) && paddinglength >0) { // Lucky Thirteen counter measure step 4 uint16 i; for(i= plainlength - paddinglength;i<plainlength;i++) { if(source[i] != padlen ) { padding_failure = TRUE; paddinglength = 0; // Pretending the padding was OK, to counter timing attacks against the MAC. } } BOOL dummy = FALSE; // Dummy check, to avoid timing differences. for(UINT16 i= 0; i < 256 - padlen - 1; i++) { if(source[i] != padlen ) // dummy check padding_failure = dummy; } } plainlength -= paddinglength; } SSL_secure_varvector16 MAC_data_master; SSL_secure_varvector16 MAC_data_calculated; ForwardToThis(MAC_data_master,MAC_data_calculated); decrypt_target->ForwardTo(this); uint16 MAC_size = cipher->MAC->Size(); uint16 read_MAC_size = cipher->MAC->Size(); if(plainlength<MAC_size) { read_MAC_size = 0; } uint16 payload_len = plainlength - read_MAC_size; source = decrypt_target->Set(source, payload_len); #ifdef TST_DUMP DumpTofile(*decrypt_target, decrypt_target->GetLength() ,"Decrypt outputdata (without MAC and padding): ","sslcrypt.txt"); #endif source = MAC_data_master.Set(source, read_MAC_size); #ifdef TST_DUMP DumpTofile(MAC_data_master, MAC_size,"Decryptstep received MAC","sslcrypt.txt"); #endif if(ErrorRaisedFlag) return NULL; { SSL_ContentType r_type; SSL_ProtocolVersion r_ver; r_type = GetType(); r_ver = GetVersion(); decrypt_target->SetType(r_type); decrypt_target->SetVersion(r_ver); if(MAC_size) { SSL_TRAP_AND_RAISE_ERROR_THIS(cipher->MAC->CalculateRecordMAC_L(cipher->Sequence_number, r_ver, r_type, *decrypt_target.get(), source, paddinglength, MAC_data_calculated)); if(blocksize > 1) { OP_ASSERT(payload_len == original_plainlength - padlen - 1 - read_MAC_size); // Extra mac check done for Lucky Thirteen counter measure step 3, 4 and 5 // Extra dummy operations to avoid timing attacks on the padding. int L1 = 13 + original_plainlength - MAC_size; int L2 = 13 + original_plainlength - padlen - 1 - MAC_size; int number_of_extra_dummy_mac_compressions = (int)op_ceil((L1 - 55)/64.) - (int)op_ceil((L2 - 55)/64.); OP_ASSERT(L1 >= 0 && L2 >= 0 && number_of_extra_dummy_mac_compressions >= 0); // Add some random noise on top. number_of_extra_dummy_mac_compressions += g_libcrypto_random_generator->GetUint8() & 15; for (int i = 0; i < number_of_extra_dummy_mac_compressions; i++) cipher->MAC->CalculateHash(source, 1); } RaiseAlert(cipher->MAC); if(ErrorRaisedFlag) return NULL; if(plainlength<MAC_size) { RaiseAlert(SSL_Fatal, SSL_Illegal_Parameter); return NULL; } #ifdef TST_DUMP DumpTofile(MAC_data_calculated, MAC_size,"Decryptstep calculated MAC : ","sslcrypt.txt"); DumpTofile(MAC_data_master, MAC_size,"Decryptstep received MAC","sslcrypt.txt"); #endif OP_ASSERT(MAC_data_calculated.GetLength() == MAC_data_master.GetLength()); BOOL mac_check_success = (MAC_data_calculated.GetLength() == MAC_data_master.GetLength()); // Constant time mac check int mac_check_size = MIN(MAC_data_calculated.GetLength(), MAC_data_master.GetLength()); for (int j = 0; j < mac_check_size; j++) { if (MAC_data_calculated.GetDirect()[j] != MAC_data_master.GetDirect()[j]) mac_check_success = FALSE; } if (padding_failure || !mac_check_success) decrypt_target->RaiseAlert(SSL_Fatal, SSL_Bad_Record_MAC); } } cipher->Sequence_number++; if(ErrorRaisedFlag) return NULL; return decrypt_target.release(); }