map<string, string>::iterator it = str_map.find(std::string(key_id));
if (it != str_map.end() ) {
- std::string master_key = from_base64((*it).second);
+ std::string master_key;
+ try {
+ master_key = from_base64((*it).second);
+ } catch (...) {
+ ldout(cct, 5) << "ERROR: get_actual_key_from_kms invalid encryption key id "
+ << "which contains character that is not base64 encoded."
+ << dendl;
+ return -EINVAL;
+ }
+
if (master_key.length() == AES_256_KEYSIZE) {
uint8_t _actual_key[AES_256_KEYSIZE];
if (AES_256_ECB_encrypt(cct,
ldout(s->cct, 5) << "ERROR: Invalid value for header "
<< "x-amz-server-side-encryption-customer-algorithm"
<< dendl;
- return -ERR_INVALID_REQUEST;
+ s->err.message = "The requested encryption algorithm is not valid, must be AES256.";
+ return -ERR_INVALID_ENCRYPTION_ALGORITHM;
}
if (s->cct->_conf->rgw_crypt_require_ssl &&
!s->info.env->exists("SERVER_PORT_SECURE")) {
ldout(s->cct, 5) << "ERROR: Insecure request, rgw_crypt_require_ssl is set" << dendl;
return -ERR_INVALID_REQUEST;
}
- std::string key_bin = from_base64(
+
+ std::string key_bin;
+ try {
+ key_bin = from_base64(
get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY) );
+ } catch (...) {
+ ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_encrypt invalid encryption "
+ << "key which contains character that is not base64 encoded."
+ << dendl;
+ s->err.message = "Requests specifying Server Side Encryption with Customer "
+ "provided keys must provide an appropriate secret key.";
+ return -EINVAL;
+ }
+
if (key_bin.size() != AES_256_CBC::AES_256_KEYSIZE) {
ldout(s->cct, 5) << "ERROR: invalid encryption key size" << dendl;
- return -ERR_INVALID_REQUEST;
+ s->err.message = "Requests specifying Server Side Encryption with Customer "
+ "provided keys must provide an appropriate secret key.";
+ return -EINVAL;
}
+
boost::string_view keymd5 =
get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5);
- std::string keymd5_bin = from_base64(keymd5);
+
+ std::string keymd5_bin;
+ try {
+ keymd5_bin = from_base64(keymd5);
+ } catch (...) {
+ ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_encrypt invalid encryption key "
+ << "md5 which contains character that is not base64 encoded."
+ << dendl;
+ s->err.message = "Requests specifying Server Side Encryption with Customer "
+ "provided keys must provide an appropriate secret key md5.";
+ return -EINVAL;
+ }
+
if (keymd5_bin.size() != CEPH_CRYPTO_MD5_DIGESTSIZE) {
ldout(s->cct, 5) << "ERROR: Invalid key md5 size" << dendl;
- return -ERR_INVALID_DIGEST;
+ s->err.message = "Requests specifying Server Side Encryption with Customer "
+ "provided keys must provide an appropriate secret key md5.";
+ return -EINVAL;
}
+
MD5 key_hash;
byte key_hash_res[CEPH_CRYPTO_MD5_DIGESTSIZE];
key_hash.Update(reinterpret_cast<const byte*>(key_bin.c_str()), key_bin.size());
if (memcmp(key_hash_res, keymd5_bin.c_str(), CEPH_CRYPTO_MD5_DIGESTSIZE) != 0) {
ldout(s->cct, 5) << "ERROR: Invalid key md5 hash" << dendl;
- return -ERR_INVALID_DIGEST;
+ s->err.message = "The calculated MD5 hash of the key did not match the hash that was provided.";
+ return -EINVAL;
}
set_attr(attrs, RGW_ATTR_CRYPT_MODE, "SSE-C-AES256");
crypt_http_responses["x-amz-server-side-encryption-customer-algorithm"] = "AES256";
crypt_http_responses["x-amz-server-side-encryption-customer-key-MD5"] = keymd5.to_string();
return 0;
+ } else {
+ boost::string_view customer_key =
+ get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY);
+ if (!customer_key.empty()) {
+ ldout(s->cct, 5) << "ERROR: SSE-C encryption request is missing the header "
+ << "x-amz-server-side-encryption-customer-algorithm"
+ << dendl;
+ s->err.message = "Requests specifying Server Side Encryption with Customer "
+ "provided keys must provide a valid encryption algorithm.";
+ return -EINVAL;
+ }
+
+ boost::string_view customer_key_md5 =
+ get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5);
+ if (!customer_key_md5.empty()) {
+ ldout(s->cct, 5) << "ERROR: SSE-C encryption request is missing the header "
+ << "x-amz-server-side-encryption-customer-algorithm"
+ << dendl;
+ s->err.message = "Requests specifying Server Side Encryption with Customer "
+ "provided keys must provide a valid encryption algorithm.";
+ return -EINVAL;
+ }
}
+
/* AMAZON server side encryption with KMS (key management service) */
boost::string_view req_sse =
get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION);
if (req_sse != "aws:kms") {
ldout(s->cct, 5) << "ERROR: Invalid value for header x-amz-server-side-encryption"
<< dendl;
- return -ERR_INVALID_REQUEST;
+ s->err.message = "Server Side Encryption with KMS managed key requires "
+ "HTTP header x-amz-server-side-encryption : aws:kms";
+ return -EINVAL;
}
if (s->cct->_conf->rgw_crypt_require_ssl &&
!s->info.env->exists("SERVER_PORT_SECURE")) {
boost::string_view key_id =
get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID);
if (key_id.empty()) {
+ ldout(s->cct, 5) << "ERROR: not provide a valid key id" << dendl;
+ s->err.message = "Server Side Encryption with KMS managed key requires "
+ "HTTP header x-amz-server-side-encryption-aws-kms-key-id";
return -ERR_INVALID_ACCESS_KEY;
}
/* try to retrieve actual key */
std::string key_selector = create_random_key_selector(s->cct);
std::string actual_key;
res = get_actual_key_from_kms(s->cct, key_id, key_selector, actual_key);
- if (res != 0)
+ if (res != 0) {
+ ldout(s->cct, 5) << "ERROR: failed to retrieve actual key from key_id: " << key_id << dendl;
+ s->err.message = "Failed to retrieve the actual key, kms-keyid: " + key_id.to_string();
return res;
+ }
if (actual_key.size() != AES_256_KEYSIZE) {
ldout(s->cct, 5) << "ERROR: key obtained from key_id:" <<
key_id << " is not 256 bit size" << dendl;
+ s->err.message = "KMS provided an invalid key for the given kms-keyid.";
return -ERR_INVALID_ACCESS_KEY;
}
set_attr(attrs, RGW_ATTR_CRYPT_MODE, "SSE-KMS");
*block_crypt = std::move(aes);
}
actual_key.replace(0, actual_key.length(), actual_key.length(), '\000');
+
+ crypt_http_responses["x-amz-server-side-encryption"] = "aws:kms";
+ crypt_http_responses["x-amz-server-side-encryption-aws-kms-key-id"] = key_id.to_string();
return 0;
+ } else {
+ boost::string_view key_id =
+ get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID);
+ if (!key_id.empty()) {
+ ldout(s->cct, 5) << "ERROR: SSE-KMS encryption request is missing the header "
+ << "x-amz-server-side-encryption"
+ << dendl;
+ s->err.message = "Server Side Encryption with KMS managed key requires "
+ "HTTP header x-amz-server-side-encryption : aws:kms";
+ return -EINVAL;
+ }
}
/* no other encryption mode, check if default encryption is selected */
if (s->cct->_conf->rgw_crypt_default_encryption_key != "") {
- std::string master_encryption_key =
- from_base64(s->cct->_conf->rgw_crypt_default_encryption_key);
+ std::string master_encryption_key;
+ try {
+ master_encryption_key = from_base64(s->cct->_conf->rgw_crypt_default_encryption_key);
+ } catch (...) {
+ ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_encrypt invalid default encryption key "
+ << "which contains character that is not base64 encoded."
+ << dendl;
+ s->err.message = "Requests specifying Server Side Encryption with Customer "
+ "provided keys must provide an appropriate secret key.";
+ return -EINVAL;
+ }
+
if (master_encryption_key.size() != 256 / 8) {
ldout(s->cct, 0) << "ERROR: failed to decode 'rgw crypt default encryption key' to 256 bit string" << dendl;
/* not an error to return; missing encryption does not inhibit processing */
const char *req_cust_alg =
s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM", NULL);
- if ((nullptr == req_cust_alg) || (strcmp(req_cust_alg, "AES256") != 0)) {
- ldout(s->cct, 5) << "ERROR: Invalid value for header "
+ if (nullptr == req_cust_alg) {
+ ldout(s->cct, 5) << "ERROR: Request for SSE-C encrypted object missing "
<< "x-amz-server-side-encryption-customer-algorithm"
<< dendl;
- return -ERR_INVALID_REQUEST;
+ s->err.message = "Requests specifying Server Side Encryption with Customer "
+ "provided keys must provide a valid encryption algorithm.";
+ return -EINVAL;
+ } else if (strcmp(req_cust_alg, "AES256") != 0) {
+ ldout(s->cct, 5) << "ERROR: The requested encryption algorithm is not valid, must be AES256." << dendl;
+ s->err.message = "The requested encryption algorithm is not valid, must be AES256.";
+ return -ERR_INVALID_ENCRYPTION_ALGORITHM;
+ }
+
+ std::string key_bin;
+ try {
+ key_bin = from_base64(s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY", ""));
+ } catch (...) {
+ ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_decrypt invalid encryption key "
+ << "which contains character that is not base64 encoded."
+ << dendl;
+ s->err.message = "Requests specifying Server Side Encryption with Customer "
+ "provided keys must provide an appropriate secret key.";
+ return -EINVAL;
}
- std::string key_bin =
- from_base64(s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY", ""));
if (key_bin.size() != AES_256_CBC::AES_256_KEYSIZE) {
ldout(s->cct, 5) << "ERROR: Invalid encryption key size" << dendl;
- return -ERR_INVALID_REQUEST;
+ s->err.message = "Requests specifying Server Side Encryption with Customer "
+ "provided keys must provide an appropriate secret key.";
+ return -EINVAL;
}
std::string keymd5 =
s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5", "");
- std::string keymd5_bin = from_base64(keymd5);
+ std::string keymd5_bin;
+ try {
+ keymd5_bin = from_base64(keymd5);
+ } catch (...) {
+ ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_decrypt invalid encryption key md5 "
+ << "which contains character that is not base64 encoded."
+ << dendl;
+ s->err.message = "Requests specifying Server Side Encryption with Customer "
+ "provided keys must provide an appropriate secret key md5.";
+ return -EINVAL;
+ }
+
+
if (keymd5_bin.size() != CEPH_CRYPTO_MD5_DIGESTSIZE) {
ldout(s->cct, 5) << "ERROR: Invalid key md5 size " << dendl;
- return -ERR_INVALID_DIGEST;
+ s->err.message = "Requests specifying Server Side Encryption with Customer "
+ "provided keys must provide an appropriate secret key md5.";
+ return -EINVAL;
}
MD5 key_hash;
if ((memcmp(key_hash_res, keymd5_bin.c_str(), CEPH_CRYPTO_MD5_DIGESTSIZE) != 0) ||
(get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYMD5) != keymd5_bin)) {
- return -ERR_INVALID_DIGEST;
+ s->err.message = "The calculated MD5 hash of the key did not match the hash that was provided.";
+ return -EINVAL;
}
auto aes = std::unique_ptr<AES_256_CBC>(new AES_256_CBC(s->cct));
aes->set_key(reinterpret_cast<const uint8_t*>(key_bin.c_str()), AES_256_CBC::AES_256_KEYSIZE);
std::string actual_key;
res = get_actual_key_from_kms(s->cct, key_id, key_selector, actual_key);
if (res != 0) {
- ldout(s->cct, 10) << "No encryption key for key-id=" << key_id << dendl;
+ ldout(s->cct, 10) << "ERROR: failed to retrieve actual key from key_id: " << key_id << dendl;
+ s->err.message = "Failed to retrieve the actual key, kms-keyid: " + key_id;
return res;
}
if (actual_key.size() != AES_256_KEYSIZE) {
ldout(s->cct, 0) << "ERROR: key obtained from key_id:" <<
key_id << " is not 256 bit size" << dendl;
+ s->err.message = "KMS provided an invalid key for the given kms-keyid.";
return -ERR_INVALID_ACCESS_KEY;
}
}
if (stored_mode == "RGW-AUTO") {
- std::string master_encryption_key =
- from_base64(std::string(s->cct->_conf->rgw_crypt_default_encryption_key));
+ std::string master_encryption_key;
+ try {
+ master_encryption_key = from_base64(std::string(s->cct->_conf->rgw_crypt_default_encryption_key));
+ } catch (...) {
+ ldout(s->cct, 5) << "ERROR: rgw_s3_prepare_decrypt invalid default encryption key "
+ << "which contains character that is not base64 encoded."
+ << dendl;
+ s->err.message = "The default encryption key is not valid base64.";
+ return -EINVAL;
+ }
+
if (master_encryption_key.size() != 256 / 8) {
ldout(s->cct, 0) << "ERROR: failed to decode 'rgw crypt default encryption key' to 256 bit string" << dendl;
return -EIO;