//////////////////////////////////////////////////////////////////////////////// // Copyright 2013 Google LLC. // // This software is licensed under the terms defined in the Widevine Master // License Agreement. For a copy of this agreement, please contact // widevine-licensing@google.com. //////////////////////////////////////////////////////////////////////////////// #include "common/test_utils.h" #include #include #include "glog/logging.h" #include "openssl/pem.h" #include "openssl/rsa.h" #include "openssl/sha.h" namespace widevine { util::Status GenerateRsaSignatureSha256Pkcs1(const std::string& pem_private_key, const std::string& message, std::string* signature) { CHECK(signature); if (pem_private_key.empty()) { return util::Status(util::error::INVALID_ARGUMENT, "Empty PEM private key"); } if (message.empty()) { return util::Status(util::error::INVALID_ARGUMENT, "Empty message"); } BIO* bio(NULL); bio = BIO_new_mem_buf(const_cast(pem_private_key.data()), pem_private_key.size()); if (bio == NULL) { return util::Status(util::error::INTERNAL, "BIO allocation failed"); } util::Status status; RSA* key(NULL); std::unique_ptr sig_buffer; unsigned int sig_size; unsigned char digest[SHA256_DIGEST_LENGTH]; key = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); if (key == NULL) { status = util::Status(util::Status::canonical_space(), util::error::INVALID_ARGUMENT, "PEM RSA private key load failed"); goto cleanup; } SHA256(reinterpret_cast(message.data()), message.size(), digest); sig_size = RSA_size(key); sig_buffer.reset(new char[sig_size]); if (RSA_sign(NID_sha256, digest, sizeof(digest), reinterpret_cast(sig_buffer.get()), &sig_size, key) != 1) { status = util::Status(util::Status::canonical_space(), util::error::INTERNAL, "RSA private encrypt failed"); goto cleanup; } signature->assign(sig_buffer.get(), sig_size); cleanup: if (key != NULL) { RSA_free(key); } if (bio != NULL) { BIO_free(bio); } return status; } } // namespace widevine