Opera 12.15 Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

signed_file.cpp 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #include "core/pch.h"
  2. #if defined _NEED_LIBSSL_VERIFY_SIGNED_FILE_
  3. #include "modules/libssl/sslv3.h"
  4. #include "modules/libssl/sslopt.h"
  5. #include "modules/url/url2.h"
  6. #include "adjunct/desktop_util/string/stringutils.h"
  7. unsigned long GeneralDecodeBase64(const unsigned char *source, unsigned long len, unsigned long &read_pos, unsigned char *target, BOOL &warning, unsigned long max_write_len=0, unsigned char *decode_buf=NULL, unsigned int *decode_len=NULL);
  8. /** Verify signed file
  9. * The function will return FALSE if signature fails or if any errors occur,
  10. *
  11. * @param signed_file URL containing the file to be verified. MUST be loaded,
  12. * which can be accomplished with signed_file.QuickLoad(TRUE)
  13. * @param signature Base64 encoded signature
  14. *
  15. * @param key Pointer to buffer containing the DER encoded public key associated
  16. * with the private key used to generate the signature, MUST be an
  17. * X509_PUBKEY structure (openssl rsa -pubout ... command result)
  18. * @param key_len Length of the public key buffer
  19. *
  20. * @param alg Algorithm used to calculate signature. Default SSL_SHA
  21. *
  22. * @return TRUE if the verification succeded, FALSE if there was any error.
  23. */
  24. BOOL VerifySignedFile(URL &signed_file, const OpStringC8 &signature, const unsigned char *key, unsigned long key_len, SSL_HashAlgorithmType alg)
  25. {
  26. if(signed_file.IsEmpty() || (URLStatus) signed_file.GetAttribute(URL::KLoadStatus) != URL_LOADED || key == NULL || key_len == 0)
  27. return FALSE;
  28. // Get The raw data
  29. OpAutoPtr<URL_DataDescriptor> desc(signed_file.GetDescriptor(NULL, TRUE, TRUE, TRUE));
  30. if(!desc.get())
  31. return FALSE;
  32. BOOL more = FALSE;
  33. unsigned long buf_len;
  34. if(desc->RetrieveData(more) == 0 || desc->GetBuffer() == NULL)
  35. return FALSE;
  36. if(desc->GetBufSize() == 0)
  37. return FALSE;
  38. if(signature.Length() <= 0)
  39. return FALSE;
  40. unsigned long signature_len = signature.Length();
  41. SSL_varvector32 signature_in;
  42. signature_in.Resize(signature_len);
  43. if(signature_in.Error())
  44. return FALSE;
  45. unsigned long read_len=0;
  46. BOOL warning= FALSE;
  47. buf_len = GeneralDecodeBase64((unsigned char *)signature.CStr(), signature_len, read_len, signature_in.GetDirect(), warning);
  48. if(warning || read_len != signature_len || buf_len == 0)
  49. return FALSE;
  50. signature_in.Resize(buf_len);
  51. SSL_Hash_Pointer digester(alg);
  52. if(digester.Error())
  53. return FALSE;
  54. digester->InitHash();
  55. do{
  56. more = FALSE;
  57. buf_len = desc->RetrieveData(more);
  58. digester->CalculateHash((unsigned char *)desc->GetBuffer(), buf_len);
  59. desc->ConsumeData(buf_len);
  60. }while(more);
  61. SSL_varvector32 signature_out;
  62. digester->ExtractHash(signature_out);
  63. if(digester->Error() || signature_out.Error())
  64. return FALSE;
  65. OpAutoPtr<SSL_PublicKeyCipher> signature_checker;
  66. OP_STATUS op_err = OpStatus::OK;
  67. signature_checker.reset(g_ssl_api->CreatePublicKeyCipher(SSL_RSA, op_err));
  68. if(OpStatus::IsError(op_err) || signature_checker.get() == NULL)
  69. return FALSE;
  70. SSL_varvector32 pubkey_bin_ex;
  71. pubkey_bin_ex.SetExternal((unsigned char *) key);
  72. pubkey_bin_ex.Resize(key_len);
  73. signature_checker->LoadAllKeys(pubkey_bin_ex);
  74. if(signature_checker->Error())
  75. return FALSE;
  76. if(alg == SSL_SHA)
  77. {
  78. if(!signature_checker->Verify(signature_out.GetDirect(), signature_out.GetLength(), signature_in.GetDirect(), signature_in.GetLength()))
  79. return FALSE;
  80. }
  81. #ifdef USE_SSL_ASN1_SIGNING
  82. else
  83. {
  84. if(!signature_checker->VerifyASN1(digester, signature_in.GetDirect(), signature_in.GetLength()))
  85. return FALSE;
  86. }
  87. #endif
  88. if(signature_checker->Error())
  89. return FALSE;
  90. return TRUE;
  91. }
  92. /** Verify checksum
  93. * The function will return FALSE if verification fails or if any errors occur,
  94. *
  95. * @param signed_file URL containing the file to be verified. MUST be loaded,
  96. * which can be accomplished with signed_file.QuickLoad(TRUE)
  97. * @param checksum Base64 encoded checksum
  98. *
  99. * @param alg Algorithm used to calculate checksum. Default SSL_SHA
  100. *
  101. * @return TRUE if the verification succeded, FALSE if there was any error.
  102. */
  103. BOOL VerifyChecksum(URL &signed_file, const OpStringC8 &checksum, SSL_HashAlgorithmType alg)
  104. {
  105. if(signed_file.IsEmpty() || (URLStatus) signed_file.GetAttribute(URL::KLoadStatus) != URL_LOADED)
  106. return FALSE;
  107. // Get The raw data
  108. OpAutoPtr<URL_DataDescriptor> desc(signed_file.GetDescriptor(NULL, TRUE, TRUE, TRUE));
  109. if(!desc.get())
  110. return FALSE;
  111. BOOL more = FALSE;
  112. unsigned long buf_len;
  113. if(desc->RetrieveData(more) == 0 || desc->GetBuffer() == NULL)
  114. return FALSE;
  115. if(desc->GetBufSize() == 0)
  116. return FALSE;
  117. SSL_Hash_Pointer digester(alg);
  118. if(digester.Error())
  119. return FALSE;
  120. digester->InitHash();
  121. do{
  122. more = FALSE;
  123. buf_len = desc->RetrieveData(more);
  124. digester->CalculateHash((unsigned char *)desc->GetBuffer(), buf_len);
  125. desc->ConsumeData(buf_len);
  126. }while(more);
  127. SSL_varvector32 signature_out;
  128. digester->ExtractHash(signature_out);
  129. if(digester->Error() || signature_out.Error())
  130. return FALSE;
  131. #ifdef _DEBUG
  132. OpString8 s8;
  133. OP_STATUS retval = ByteToHexStr(signature_out.GetDirect(), signature_out.GetLength(), s8);
  134. OP_ASSERT(retval == OpStatus::OK);
  135. #endif
  136. byte* byte_buffer = NULL;
  137. unsigned int buffer_len = 0;
  138. OP_STATUS ret = HexStrToByte(checksum, byte_buffer, buffer_len);
  139. if(OpStatus::IsError(ret))
  140. return FALSE;
  141. SSL_varvector32 signature_in;
  142. signature_in.Set(byte_buffer, buffer_len);
  143. OP_DELETEA(byte_buffer);
  144. return signature_in == signature_out;
  145. }
  146. /** Check file signature (SHA 256 algorithm)
  147. * The function will return ERR if verification fails or if any errors occur,
  148. *
  149. * @param full_path Full path of file to be checked
  150. *
  151. * @param signature Base64 encoded checksum
  152. *
  153. * @return OK if the verification succeded, ERR if there was any error.
  154. */
  155. OP_STATUS CheckFileSignature(const OpString &full_path, const OpString8& signature)
  156. {
  157. OpString resolved;
  158. OpString path;
  159. OP_MEMORY_VAR BOOL successful;
  160. RETURN_IF_ERROR(path.Append("file:"));
  161. RETURN_IF_ERROR(path.Append(full_path));
  162. RETURN_IF_LEAVE(successful = g_url_api->ResolveUrlNameL(path, resolved));
  163. if (!successful || resolved.Find("file://") != 0)
  164. return OpStatus::ERR;
  165. URL url = g_url_api->GetURL(resolved.CStr());
  166. if (!url.QuickLoad(TRUE))
  167. return OpStatus::ERR;
  168. // Verify hash
  169. if (VerifyChecksum(url, signature, SSL_SHA_256))
  170. return OpStatus::OK;
  171. else
  172. return OpStatus::ERR;
  173. /*
  174. if (VerifySignedFile(url, signature, AUTOUPDATE_KEY, sizeof(AUTOUPDATE_KEY), SSL_SHA_256))
  175. return OpStatus::OK;
  176. else
  177. return OpStatus::ERR;
  178. */
  179. }
  180. #endif