feat: datakey decrypt fails when not exportable
This commit is contained in:
@@ -84,7 +84,7 @@ Generate data key:
|
||||
```shell
|
||||
curl -X POST http://127.0.0.1:5567/datakey \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"key_type":"aes", "key_spec":"256", "return_plaintext": true}'
|
||||
-d '{"type":"aes", "spec":"256", "exportable": true, "return_plaintext": true}'
|
||||
```
|
||||
|
||||
Upgrade to v3.2
|
||||
|
||||
17
src/jose.rs
17
src/jose.rs
@@ -50,7 +50,7 @@ pub fn rsa_key_to_pem(rsa_private_key: &RsaPrivateKey) -> XResult<String> {
|
||||
}
|
||||
|
||||
pub fn jwk_to_rsa_pubic_key(rsa_jwk: &str) -> XResult<RsaPublicKey> {
|
||||
let rsa: Rsa = opt_result!(serde_json::from_str(&rsa_jwk), "Bad RSA JWK: {}, error: {}", rsa_jwk);
|
||||
let rsa: Rsa = opt_result!(serde_json::from_str(rsa_jwk), "Bad RSA JWK: {}, error: {}", rsa_jwk);
|
||||
let rsa_public_key = opt_result!(RsaPublicKey::try_from(rsa), "Bad RSA JWK: {}, error: {:?}", rsa_jwk);
|
||||
Ok(rsa_public_key)
|
||||
}
|
||||
@@ -73,7 +73,7 @@ pub fn deserialize_jwe_rsa(jwe: &str, rsa: &RsaPrivateKey) -> XResult<(Vec<u8>,
|
||||
if alg != JWE_ALG_RSA_OAEP {
|
||||
return simple_error!("Invalid JWE header alg: {}", alg);
|
||||
}
|
||||
Ok(opt_result!(rsa.decrypt(Oaep::new::<Sha1>(), &key_wrap), "Unwrap key failed: {}"))
|
||||
Ok(opt_result!(rsa.decrypt(Oaep::new::<Sha1>(), key_wrap), "Unwrap key failed: {}"))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ pub fn serialize_jwe_aes(payload: &[u8], key: &[u8]) -> XResult<String> {
|
||||
}
|
||||
|
||||
pub fn serialize_jwe_aes_with_data_type(data_type: &str, exportable: bool, payload: &[u8], key: &[u8]) -> XResult<String> {
|
||||
serialize_jwe_aes_32(Some(data_type.to_string()), iff!(exportable, Some(false), None), payload, to_bytes32(key)?)
|
||||
serialize_jwe_aes_32(Some(data_type.to_string()), iff!(exportable, None, Some(false)), payload, to_bytes32(key)?)
|
||||
}
|
||||
|
||||
pub fn serialize_jwe_aes_32(data_type: Option<String>, exportable: Option<bool>, payload: &[u8], key: [u8; 32]) -> XResult<String> {
|
||||
@@ -93,11 +93,10 @@ pub fn serialize_jwe_aes_32(data_type: Option<String>, exportable: Option<bool>,
|
||||
version: Some(get_master_key_checksum(&key)),
|
||||
data_type,
|
||||
exportable,
|
||||
..Default::default()
|
||||
};
|
||||
serialize_jwe_fn(&header, payload, |data_key| -> XResult<Vec<u8>> {
|
||||
let kek = Kek::from(key);
|
||||
Ok(opt_result!(kek.wrap_vec(&data_key[..]), "Wrap key failed: {}"))
|
||||
Ok(opt_result!(kek.wrap_vec(data_key), "Wrap key failed: {}"))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -111,7 +110,7 @@ pub fn deserialize_jwe_aes_32(jwe: &str, key: [u8; 32]) -> XResult<(Vec<u8>, Jwe
|
||||
return simple_error!("Invalid JWE header alg: {}", alg);
|
||||
}
|
||||
let kek = Kek::from(key);
|
||||
Ok(opt_result!(kek.unwrap_vec(&key_wrap), "Unwrap key failed: {}"))
|
||||
Ok(opt_result!(kek.unwrap_vec(key_wrap), "Unwrap key failed: {}"))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -137,7 +136,7 @@ where
|
||||
LOCAL_KMS_PREFIX,
|
||||
header_b64,
|
||||
URL_SAFE_NO_PAD.encode(&cek),
|
||||
URL_SAFE_NO_PAD.encode(&iv),
|
||||
URL_SAFE_NO_PAD.encode(iv),
|
||||
URL_SAFE_NO_PAD.encode(&ciphertext),
|
||||
URL_SAFE_NO_PAD.encode(&tag)
|
||||
))
|
||||
@@ -187,9 +186,7 @@ fn to_bytes32(bytes: &[u8]) -> XResult<[u8; 32]> {
|
||||
return simple_error!("Not valid 32 bytes");
|
||||
}
|
||||
let mut ret = [0; 32];
|
||||
for i in 0..32 {
|
||||
ret[i] = bytes[i];
|
||||
}
|
||||
ret.copy_from_slice(&bytes[..32]);
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@ use serde_json::{Map, Value};
|
||||
// type:ec, spec:p256,p384,p521,ed25519,cv25519
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct DataKeyRequest {
|
||||
key_type: String,
|
||||
key_spec: String,
|
||||
key_name: Option<String>,
|
||||
r#type: String,
|
||||
spec: String,
|
||||
name: Option<String>,
|
||||
exportable: Option<bool>,
|
||||
return_plaintext: Option<bool>,
|
||||
}
|
||||
@@ -32,15 +32,15 @@ async fn inner_generate(req: Request<Body>) -> XResult<(StatusCode, Value)> {
|
||||
let whole_body = hyper::body::aggregate(req).await?;
|
||||
let request: DataKeyRequest = serde_json::from_reader(whole_body.reader())?;
|
||||
|
||||
debugging!("Generate data key: {} {}", &request.key_type, &request.key_spec);
|
||||
debugging!("Generate data key: {} {}", &request.r#type, &request.spec);
|
||||
let key = match get_master_key() {
|
||||
None => return serve_common::error("status_not_ready"),
|
||||
Some(key) => key,
|
||||
};
|
||||
let exportable = request.exportable.unwrap_or(true);
|
||||
let ret_key_plaintext = iff!(exportable, false, request.return_plaintext.unwrap_or(false));
|
||||
let ret_key_plaintext = iff!(!exportable, false, request.return_plaintext.unwrap_or(false));
|
||||
|
||||
let response_result = match (request.key_type.as_str(), request.key_spec.as_str()) {
|
||||
let response_result = match (request.r#type.as_str(), request.spec.as_str()) {
|
||||
("aes", "128") => generate_aes("datakey:aes-128", exportable, key, 16, ret_key_plaintext),
|
||||
("aes", "192") => generate_aes("datakey:aes-192", exportable, key, 24, ret_key_plaintext),
|
||||
("aes", "256") => generate_aes("datakey:aes-256", exportable, key, 32, ret_key_plaintext),
|
||||
@@ -53,16 +53,16 @@ async fn inner_generate(req: Request<Body>) -> XResult<(StatusCode, Value)> {
|
||||
Err(e) => serve_common::error(&format!("internal error: {}", e)),
|
||||
Ok((key_plaintext, key_ciphertext)) => {
|
||||
let mut map = Map::new();
|
||||
map.insert("key_type".to_string(), Value::String(request.key_type));
|
||||
map.insert("key_spec".to_string(), Value::String(request.key_spec));
|
||||
map.insert("key_type".to_string(), Value::String(request.r#type));
|
||||
map.insert("key_spec".to_string(), Value::String(request.spec));
|
||||
if let Some(key_plaintext) = key_plaintext {
|
||||
map.insert("key_plaintext".to_string(), Value::String(STANDARD.encode(&key_plaintext)));
|
||||
}
|
||||
map.insert("key_ciphertext".to_string(), Value::String(key_ciphertext));
|
||||
|
||||
if let Some(_key_name) = &request.key_name {
|
||||
if let Some(_name) = &request.name {
|
||||
// TODO write datakey to db
|
||||
// TODO let data_key_name = format!("datakey:{}", key_name);
|
||||
// TODO let data_key_name = format!("datakey:{}", name);
|
||||
}
|
||||
|
||||
Ok((StatusCode::OK, Value::Object(map)))
|
||||
|
||||
@@ -28,23 +28,26 @@ async fn inner_decrypt(req: Request<Body>) -> XResult<(StatusCode, Value)> {
|
||||
};
|
||||
let decrypted_value = jose::deserialize_jwe_aes(&data.encrypted_value, &key.read());
|
||||
drop(key);
|
||||
let (data, header) = decrypted_value?;
|
||||
|
||||
decrypted_value.map(|(data, header)| {
|
||||
let mut map = byte_to_multi_view_map(&data, true);
|
||||
let mut header_map = Map::new();
|
||||
header_map.insert("enc".to_string(), Value::String(header.enc.clone()));
|
||||
header_map.insert("alg".to_string(), Value::String(header.alg.clone()));
|
||||
if let Some(version) = &header.version {
|
||||
header_map.insert("version".to_string(), Value::String(version.to_string()));
|
||||
}
|
||||
if let Some(data_type) = &header.data_type {
|
||||
header_map.insert("data_type".to_string(), Value::String(data_type.to_string()));
|
||||
}
|
||||
if !header_map.is_empty() {
|
||||
map.insert("header".to_string(), Value::Object(header_map));
|
||||
}
|
||||
(StatusCode::OK, Value::Object(map))
|
||||
})
|
||||
if let Some(false) = header.exportable {
|
||||
return serve_common::error("data_not_exportable");
|
||||
}
|
||||
|
||||
let mut map = byte_to_multi_view_map(&data, true);
|
||||
let mut header_map = Map::new();
|
||||
header_map.insert("enc".to_string(), Value::String(header.enc.clone()));
|
||||
header_map.insert("alg".to_string(), Value::String(header.alg.clone()));
|
||||
if let Some(version) = &header.version {
|
||||
header_map.insert("version".to_string(), Value::String(version.to_string()));
|
||||
}
|
||||
if let Some(data_type) = &header.data_type {
|
||||
header_map.insert("data_type".to_string(), Value::String(data_type.to_string()));
|
||||
}
|
||||
if !header_map.is_empty() {
|
||||
map.insert("header".to_string(), Value::Object(header_map));
|
||||
}
|
||||
Ok((StatusCode::OK, Value::Object(map)))
|
||||
}
|
||||
|
||||
pub async fn encrypt(req: Request<Body>) -> Result<Response<Body>> {
|
||||
|
||||
Reference in New Issue
Block a user