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, KeyId, 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!(KeyId, String, {
38    try_lift: |val| {
39        convert_result(KeyId::from_str(&val))
40    },
41    lower: |obj| obj.to_string(),
42});
43
44uniffi::custom_type!(UnsignedSharedKey, String, {
45    try_lift: |val| {
46        convert_result(UnsignedSharedKey::from_str(&val))
47    },
48    lower: |obj| obj.to_string(),
49});
50
51uniffi::custom_type!(SignedPublicKey, String, {
52    try_lift: |val| {
53        convert_result(SignedPublicKey::from_str(&val))
54    },
55    lower: |obj| obj.into(),
56});
57
58uniffi::custom_type!(PublicKey, String, {
59    try_lift: |val| {
60        convert_result(PublicKey::from_str(&val)
61            .map_err(|_e| EncodingError::InvalidBase64Encoding))
62    },
63    lower: |obj| obj.to_string(),
64});
65
66uniffi::custom_type!(DataEnvelope, String, {
67    try_lift: |val| convert_result(DataEnvelope::from_str(val.as_str())),
68    lower: |obj| obj.to_string(),
69});
70
71uniffi::custom_type!(PasswordProtectedKeyEnvelope, String, {
72    remote,
73    try_lift: |val| convert_result(PasswordProtectedKeyEnvelope::from_str(&val)),
74    lower: |obj| obj.into(),
75});
76
77uniffi::custom_type!(SecretProtectedKeyEnvelope, String, {
78    remote,
79    try_lift: |val| convert_result(SecretProtectedKeyEnvelope::from_str(&val)),
80    lower: |obj| obj.into(),
81});
82
83uniffi::custom_type!(HighEntropySecret, Vec<u8>, {
84    try_lift: |val| Ok(HighEntropySecret::from_internal(&val)),
85    // EXPOSE: the UniFFI lowering needs the raw bytes to cross the FFI boundary; this round-trips
86    // the same secret the caller provided. The Uniffi implementation is responsible for making
87    // sure the secret is not logged.
88    lower: |obj| obj.as_bytes().expose_owned().to_vec(),
89});