Skip to main content

bitwarden_crypto/
uniffi_support.rs

1use std::{num::NonZeroU32, str::FromStr};
2
3use bitwarden_sensitive_value::ExposeSensitive;
4use bitwarden_uniffi_error::convert_result;
5
6use crate::{
7    CryptoError, EncString, EncodingError, PublicKey, SignedPublicKey, SymmetricCryptoKey,
8    UnsignedSharedKey,
9    safe::{
10        DataEnvelope, HighEntropySecret, PasswordProtectedKeyEnvelope, SecretProtectedKeyEnvelope,
11    },
12};
13
14uniffi::custom_type!(NonZeroU32, u32, {
15    remote,
16    try_lift: |val| {
17        convert_result(NonZeroU32::new(val).ok_or(CryptoError::ZeroNumber))
18    },
19    lower: |obj| obj.get(),
20});
21
22uniffi::custom_type!(SymmetricCryptoKey, String, {
23    remote,
24    try_lift: |val| {
25        convert_result(SymmetricCryptoKey::try_from(val.as_str().to_string()))
26    },
27    lower: |obj| obj.to_base64().to_string(),
28});
29
30uniffi::custom_type!(EncString, String, {
31    try_lift: |val| {
32        convert_result(EncString::from_str(&val))
33    },
34    lower: |obj| obj.to_string(),
35});
36
37uniffi::custom_type!(UnsignedSharedKey, String, {
38    try_lift: |val| {
39        convert_result(UnsignedSharedKey::from_str(&val))
40    },
41    lower: |obj| obj.to_string(),
42});
43
44uniffi::custom_type!(SignedPublicKey, String, {
45    try_lift: |val| {
46        convert_result(SignedPublicKey::from_str(&val))
47    },
48    lower: |obj| obj.into(),
49});
50
51uniffi::custom_type!(PublicKey, String, {
52    try_lift: |val| {
53        convert_result(PublicKey::from_str(&val)
54            .map_err(|_e| EncodingError::InvalidBase64Encoding))
55    },
56    lower: |obj| obj.to_string(),
57});
58
59uniffi::custom_type!(DataEnvelope, String, {
60    try_lift: |val| convert_result(DataEnvelope::from_str(val.as_str())),
61    lower: |obj| obj.to_string(),
62});
63
64uniffi::custom_type!(PasswordProtectedKeyEnvelope, String, {
65    remote,
66    try_lift: |val| convert_result(PasswordProtectedKeyEnvelope::from_str(&val)),
67    lower: |obj| obj.into(),
68});
69
70uniffi::custom_type!(SecretProtectedKeyEnvelope, String, {
71    remote,
72    try_lift: |val| convert_result(SecretProtectedKeyEnvelope::from_str(&val)),
73    lower: |obj| obj.into(),
74});
75
76uniffi::custom_type!(HighEntropySecret, Vec<u8>, {
77    try_lift: |val| Ok(HighEntropySecret::from_internal(&val)),
78    // EXPOSE: the UniFFI lowering needs the raw bytes to cross the FFI boundary; this round-trips
79    // the same secret the caller provided. The Uniffi implementation is responsible for making
80    // sure the secret is not logged.
81    lower: |obj| obj.as_bytes().expose_owned().to_vec(),
82});