rsa_operation.cpp revision 4200f211057551c02e909fe88e5a92dae7a36597
10a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden/*
20a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden * Copyright 2014 The Android Open Source Project
30a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden *
40a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden * Licensed under the Apache License, Version 2.0 (the "License");
50a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden * you may not use this file except in compliance with the License.
60a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden * You may obtain a copy of the License at
70a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden *
80a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden *      http://www.apache.org/licenses/LICENSE-2.0
90a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden *
100a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden * Unless required by applicable law or agreed to in writing, software
110a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden * distributed under the License is distributed on an "AS IS" BASIS,
120a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden * See the License for the specific language governing permissions and
140a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden * limitations under the License.
150a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden */
160a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden
174200f211057551c02e909fe88e5a92dae7a36597Shawn Willden#include <limits.h>
184200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
194200f211057551c02e909fe88e5a92dae7a36597Shawn Willden#include <openssl/err.h>
205f42dbae89434cfb2bd0cd00061b1096b3fd02b5Shawn Willden#include <openssl/evp.h>
214200f211057551c02e909fe88e5a92dae7a36597Shawn Willden#include <openssl/rsa.h>
220a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden
230a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden#include "rsa_operation.h"
240a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden#include "openssl_utils.h"
250a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden
260a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willdennamespace keymaster {
270a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden
280a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willdenstruct RSA_Delete {
290a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    void operator()(RSA* p) const { RSA_free(p); }
300a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden};
310a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden
320a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn WilldenRsaOperation::~RsaOperation() {
330a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    if (rsa_key_ != NULL)
340a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden        RSA_free(rsa_key_);
350a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden}
360a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden
375da34d2f205623a05ca503d5c192a020b7740be1Shawn Willdenkeymaster_error_t RsaOperation::Update(const Buffer& input, Buffer* /* output */) {
380a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    switch (purpose()) {
390a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    default:
400a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden        return KM_ERROR_UNIMPLEMENTED;
410a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    case KM_PURPOSE_SIGN:
420a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    case KM_PURPOSE_VERIFY:
434200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    case KM_PURPOSE_ENCRYPT:
444200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    case KM_PURPOSE_DECRYPT:
455da34d2f205623a05ca503d5c192a020b7740be1Shawn Willden        return StoreData(input);
460a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    }
470a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden}
480a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden
495da34d2f205623a05ca503d5c192a020b7740be1Shawn Willdenkeymaster_error_t RsaOperation::StoreData(const Buffer& input) {
500a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    if (!data_.reserve(data_.available_read() + input.available_read()) ||
510a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden        !data_.write(input.peek_read(), input.available_read()))
520a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
530a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    return KM_ERROR_OK;
540a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden}
550a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden
560a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willdenkeymaster_error_t RsaSignOperation::Finish(const Buffer& /* signature */, Buffer* output) {
570a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    output->Reinitialize(RSA_size(rsa_key_));
580a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    int bytes_encrypted = RSA_private_encrypt(data_.available_read(), data_.peek_read(),
590a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden                                              output->peek_write(), rsa_key_, RSA_NO_PADDING);
600a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    if (bytes_encrypted < 0)
610a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden        return KM_ERROR_UNKNOWN_ERROR;
620a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    assert(bytes_encrypted == RSA_size(rsa_key_));
630a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    output->advance_write(bytes_encrypted);
640a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    return KM_ERROR_OK;
650a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden}
660a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden
670a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willdenkeymaster_error_t RsaVerifyOperation::Finish(const Buffer& signature, Buffer* /* output */) {
68f2aefdfc5adcc0a59bd51a7e4ec5ab92a513171cAdam Langley#if defined(OPENSSL_IS_BORINGSSL)
694200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    size_t message_size = data_.available_read();
70f2aefdfc5adcc0a59bd51a7e4ec5ab92a513171cAdam Langley#else
714200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    if (data_.available_read() > INT_MAX)
720a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden        return KM_ERROR_INVALID_INPUT_LENGTH;
734200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    int message_size = (int)data_.available_read();
74f2aefdfc5adcc0a59bd51a7e4ec5ab92a513171cAdam Langley#endif
75f2aefdfc5adcc0a59bd51a7e4ec5ab92a513171cAdam Langley
764200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    if (message_size != RSA_size(rsa_key_))
774200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        return KM_ERROR_INVALID_INPUT_LENGTH;
784200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
790a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    if (data_.available_read() != signature.available_read())
800a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden        return KM_ERROR_VERIFICATION_FAILED;
810a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden
820a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    UniquePtr<uint8_t[]> decrypted_data(new uint8_t[RSA_size(rsa_key_)]);
830a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    int bytes_decrypted = RSA_public_decrypt(signature.available_read(), signature.peek_read(),
840a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden                                             decrypted_data.get(), rsa_key_, RSA_NO_PADDING);
850a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    if (bytes_decrypted < 0)
860a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden        return KM_ERROR_UNKNOWN_ERROR;
870a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    assert(bytes_decrypted == RSA_size(rsa_key_));
880a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden
890a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    if (memcmp_s(decrypted_data.get(), data_.peek_read(), data_.available_read()) == 0)
900a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden        return KM_ERROR_OK;
910a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden    return KM_ERROR_VERIFICATION_FAILED;
920a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden}
930a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden
944200f211057551c02e909fe88e5a92dae7a36597Shawn Willdenconst int OAEP_PADDING_OVERHEAD = 41;
954200f211057551c02e909fe88e5a92dae7a36597Shawn Willdenconst int PKCS1_PADDING_OVERHEAD = 11;
964200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
974200f211057551c02e909fe88e5a92dae7a36597Shawn Willdenkeymaster_error_t RsaEncryptOperation::Finish(const Buffer& /* signature */, Buffer* output) {
984200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    int openssl_padding;
994200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
1004200f211057551c02e909fe88e5a92dae7a36597Shawn Willden#if defined(OPENSSL_IS_BORINGSSL)
1014200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    size_t message_size = data_.available_read();
1024200f211057551c02e909fe88e5a92dae7a36597Shawn Willden#else
1034200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    if (data_.available_read() > INT_MAX)
1044200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        return KM_ERROR_INVALID_INPUT_LENGTH;
1054200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    int message_size = (int)data_.available_read();
1064200f211057551c02e909fe88e5a92dae7a36597Shawn Willden#endif
1074200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
1084200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    switch (padding_) {
1094200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    case KM_PAD_RSA_OAEP:
1104200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        openssl_padding = RSA_PKCS1_OAEP_PADDING;
1114200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        if (message_size >= RSA_size(rsa_key_) - OAEP_PADDING_OVERHEAD) {
1124200f211057551c02e909fe88e5a92dae7a36597Shawn Willden            logger().error("Cannot encrypt %d bytes with %d-byte key and OAEP padding",
1134200f211057551c02e909fe88e5a92dae7a36597Shawn Willden                           data_.available_read(), RSA_size(rsa_key_));
1144200f211057551c02e909fe88e5a92dae7a36597Shawn Willden            return KM_ERROR_INVALID_INPUT_LENGTH;
1154200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        }
1164200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        break;
1174200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
1184200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        openssl_padding = RSA_PKCS1_PADDING;
1194200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        if (message_size >= RSA_size(rsa_key_) - PKCS1_PADDING_OVERHEAD) {
1204200f211057551c02e909fe88e5a92dae7a36597Shawn Willden            logger().error("Cannot encrypt %d bytes with %d-byte key and PKCS1 padding",
1214200f211057551c02e909fe88e5a92dae7a36597Shawn Willden                           data_.available_read(), RSA_size(rsa_key_));
1224200f211057551c02e909fe88e5a92dae7a36597Shawn Willden            return KM_ERROR_INVALID_INPUT_LENGTH;
1234200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        }
1244200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        break;
1254200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    default:
1264200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        logger().error("Padding mode %d not supported", padding_);
1274200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        return KM_ERROR_UNSUPPORTED_PADDING_MODE;
1284200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    }
1294200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
1304200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    output->Reinitialize(RSA_size(rsa_key_));
1314200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    int bytes_encrypted = RSA_public_encrypt(data_.available_read(), data_.peek_read(),
1324200f211057551c02e909fe88e5a92dae7a36597Shawn Willden                                             output->peek_write(), rsa_key_, openssl_padding);
1334200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
1344200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    if (bytes_encrypted < 0) {
1354200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        logger().error("Error %d encrypting data with RSA", ERR_get_error());
1364200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        return KM_ERROR_UNKNOWN_ERROR;
1374200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    }
1384200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    assert(bytes_encrypted == RSA_size(rsa_key_));
1394200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    output->advance_write(bytes_encrypted);
1404200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
1414200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    return KM_ERROR_OK;
1424200f211057551c02e909fe88e5a92dae7a36597Shawn Willden}
1434200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
1444200f211057551c02e909fe88e5a92dae7a36597Shawn Willdenkeymaster_error_t RsaDecryptOperation::Finish(const Buffer& /* signature */, Buffer* output) {
1454200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    int openssl_padding;
1464200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    switch (padding_) {
1474200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    case KM_PAD_RSA_OAEP:
1484200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        openssl_padding = RSA_PKCS1_OAEP_PADDING;
1494200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        break;
1504200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    case KM_PAD_RSA_PKCS1_1_5_ENCRYPT:
1514200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        openssl_padding = RSA_PKCS1_PADDING;
1524200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        break;
1534200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    default:
1544200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        logger().error("Padding mode %d not supported", padding_);
1554200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        return KM_ERROR_UNSUPPORTED_PADDING_MODE;
1564200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    }
1574200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
1584200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    output->Reinitialize(RSA_size(rsa_key_));
1594200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    int bytes_decrypted = RSA_private_decrypt(data_.available_read(), data_.peek_read(),
1604200f211057551c02e909fe88e5a92dae7a36597Shawn Willden                                              output->peek_write(), rsa_key_, openssl_padding);
1614200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
1624200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    if (bytes_decrypted < 0) {
1634200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        logger().error("Error %d decrypting data with RSA", ERR_get_error());
1644200f211057551c02e909fe88e5a92dae7a36597Shawn Willden        return KM_ERROR_UNKNOWN_ERROR;
1654200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    }
1664200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    output->advance_write(bytes_decrypted);
1674200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
1684200f211057551c02e909fe88e5a92dae7a36597Shawn Willden    return KM_ERROR_OK;
1694200f211057551c02e909fe88e5a92dae7a36597Shawn Willden}
1704200f211057551c02e909fe88e5a92dae7a36597Shawn Willden
1710a4df7e3a83a59e4a5abc3f605d7d7e9f636c682Shawn Willden}  // namespace keymaster
172