/** Verify signed file * The function will return FALSE if signature fails or if any errors occur, * * @param signed_file URL containing the file to be verified. MUST be loaded, * which can be accomplished with signed_file.QuickLoad(TRUE) * @param signature Base64 encoded signature * * @param key Pointer to buffer containing the DER encoded public key associated * with the private key used to generate the signature, MUST be an * X509_PUBKEY structure (openssl rsa -pubout ... command result) * @param key_len Length of the public key buffer * * @param alg Algorithm used to calculate signature. Default SSL_SHA * * @return TRUE if the verification succeded, FALSE if there was any error. */ BOOL VerifySignedFile(URL &signed_file, const OpStringC8 &signature, const unsigned char *key, unsigned long key_len, SSL_HashAlgorithmType alg) { if(signed_file.IsEmpty() || (URLStatus) signed_file.GetAttribute(URL::KLoadStatus) != URL_LOADED || key == NULL || key_len == 0) return FALSE; // Get The raw data OpAutoPtr<URL_DataDescriptor> desc(signed_file.GetDescriptor(NULL, TRUE, TRUE, TRUE)); if(!desc.get()) return FALSE; BOOL more = FALSE; unsigned long buf_len; if(desc->RetrieveData(more) == 0 || desc->GetBuffer() == NULL) return FALSE; if(desc->GetBufSize() == 0) return FALSE; if(signature.Length() <= 0) return FALSE; unsigned long signature_len = signature.Length(); SSL_varvector32 signature_in; signature_in.Resize(signature_len); if(signature_in.Error()) return FALSE; unsigned long read_len=0; BOOL warning= FALSE; buf_len = GeneralDecodeBase64((unsigned char *)signature.CStr(), signature_len, read_len, signature_in.GetDirect(), warning); if(warning || read_len != signature_len || buf_len == 0) return FALSE; signature_in.Resize(buf_len); SSL_Hash_Pointer digester(alg); if(digester.Error()) return FALSE; digester->InitHash(); do { more = FALSE; buf_len = desc->RetrieveData(more); digester->CalculateHash((unsigned char *)desc->GetBuffer(), buf_len); desc->ConsumeData(buf_len); } while(more); SSL_varvector32 signature_out; digester->ExtractHash(signature_out); if(digester->Error() || signature_out.Error()) return FALSE; OpAutoPtr<SSL_PublicKeyCipher> signature_checker; OP_STATUS op_err = OpStatus::OK; signature_checker.reset(g_ssl_api->CreatePublicKeyCipher(SSL_RSA, op_err)); if(OpStatus::IsError(op_err) || signature_checker.get() == NULL) return FALSE; SSL_varvector32 pubkey_bin_ex; pubkey_bin_ex.SetExternal((unsigned char *) key); pubkey_bin_ex.Resize(key_len); signature_checker->LoadAllKeys(pubkey_bin_ex); if(signature_checker->Error()) return FALSE; if(alg == SSL_SHA) { if(!signature_checker->Verify(signature_out.GetDirect(), signature_out.GetLength(), signature_in.GetDirect(), signature_in.GetLength())) return FALSE; } #ifdef USE_SSL_ASN1_SIGNING else { if(!signature_checker->VerifyASN1(digester, signature_in.GetDirect(), signature_in.GetLength())) return FALSE; } #endif if(signature_checker->Error()) return FALSE; return TRUE; }
/** Verify checksum * The function will return FALSE if verification fails or if any errors occur, * * @param signed_file URL containing the file to be verified. MUST be loaded, * which can be accomplished with signed_file.QuickLoad(TRUE) * @param checksum Base64 encoded checksum * * @param alg Algorithm used to calculate checksum. Default SSL_SHA * * @return TRUE if the verification succeded, FALSE if there was any error. */ BOOL VerifyChecksum(URL &signed_file, const OpStringC8 &checksum, SSL_HashAlgorithmType alg) { if(signed_file.IsEmpty() || (URLStatus) signed_file.GetAttribute(URL::KLoadStatus) != URL_LOADED) return FALSE; // Get The raw data OpAutoPtr<URL_DataDescriptor> desc(signed_file.GetDescriptor(NULL, TRUE, TRUE, TRUE)); if(!desc.get()) return FALSE; BOOL more = FALSE; unsigned long buf_len; if(desc->RetrieveData(more) == 0 || desc->GetBuffer() == NULL) return FALSE; if(desc->GetBufSize() == 0) return FALSE; SSL_Hash_Pointer digester(alg); if(digester.Error()) return FALSE; digester->InitHash(); do { more = FALSE; buf_len = desc->RetrieveData(more); digester->CalculateHash((unsigned char *)desc->GetBuffer(), buf_len); desc->ConsumeData(buf_len); } while(more); SSL_varvector32 signature_out; digester->ExtractHash(signature_out); if(digester->Error() || signature_out.Error()) return FALSE; #ifdef _DEBUG OpString8 s8; OP_STATUS retval = ByteToHexStr(signature_out.GetDirect(), signature_out.GetLength(), s8); OP_ASSERT(retval == OpStatus::OK); #endif byte* byte_buffer = NULL; unsigned int buffer_len = 0; OP_STATUS ret = HexStrToByte(checksum, byte_buffer, buffer_len); if(OpStatus::IsError(ret)) return FALSE; SSL_varvector32 signature_in; signature_in.Set(byte_buffer, buffer_len); OP_DELETEA(byte_buffer); return signature_in == signature_out; }