optee_utee/
arithmetical.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::{Error, Result};
19#[cfg(not(feature = "std"))]
20use alloc::vec::Vec;
21use core::{cmp::max, fmt};
22use optee_utee_sys as raw;
23
24pub type BigIntUnit = u32;
25pub type BigIntFMMUnit = u32;
26pub type BigIntFMMContextUnit = u32;
27
28pub struct BigInt(Vec<BigIntUnit>);
29
30impl BigInt {
31    pub fn data_ptr(&self) -> *const u32 {
32        self.0.as_ptr()
33    }
34
35    // size represents BigInt bits
36    pub fn size_in_u32(size: u32) -> u32 {
37        size.div_ceil(32) + 2
38    }
39
40    pub fn new(bits: u32) -> Self {
41        let size: usize = Self::size_in_u32(bits) as usize;
42        let mut tmp_vec: Vec<BigIntUnit> = vec![0; size];
43        unsafe { raw::TEE_BigIntInit(tmp_vec.as_mut_ptr(), size) };
44        Self(tmp_vec)
45    }
46
47    pub fn convert_from_octet_string(&mut self, buffer: &[u8], sign: i32) -> Result<()> {
48        match unsafe {
49            raw::TEE_BigIntConvertFromOctetString(
50                self.0.as_mut_ptr(),
51                buffer.as_ptr(),
52                buffer.len(),
53                sign,
54            )
55        } {
56            raw::TEE_SUCCESS => Ok(()),
57            code => Err(Error::from_raw_error(code)),
58        }
59    }
60
61    pub fn convert_to_octet_string(&self) -> Result<Vec<u8>> {
62        let mut buffer_size: usize = (self.0.len() - 2) * 4;
63        let mut tmp_vec = vec![0u8; buffer_size];
64        match unsafe {
65            raw::TEE_BigIntConvertToOctetString(
66                tmp_vec.as_mut_ptr(),
67                &mut buffer_size,
68                self.data_ptr(),
69            )
70        } {
71            raw::TEE_SUCCESS => {
72                tmp_vec.truncate(buffer_size);
73                Ok(tmp_vec)
74            }
75            code => Err(Error::from_raw_error(code)),
76        }
77    }
78
79    pub fn convert_from_s32(&mut self, short_val: i32) {
80        unsafe { raw::TEE_BigIntConvertFromS32(self.0.as_mut_ptr(), short_val) };
81    }
82
83    pub fn convert_to_s32(&self) -> Result<i32> {
84        let mut short_val: i32 = 0;
85        match unsafe { raw::TEE_BigIntConvertToS32(&mut short_val as _, self.data_ptr()) } {
86            raw::TEE_SUCCESS => Ok(short_val),
87            code => Err(Error::from_raw_error(code)),
88        }
89    }
90
91    /* return negative number if self < target,
92    0 if self == target
93    positive number if self > target*/
94    pub fn compare_big_int(&self, target: &Self) -> i32 {
95        unsafe { raw::TEE_BigIntCmp(self.data_ptr(), target.data_ptr()) }
96    }
97
98    pub fn compare_s32(&self, target: i32) -> i32 {
99        unsafe { raw::TEE_BigIntCmpS32(self.data_ptr(), target) }
100    }
101
102    pub fn shift_right(&mut self, op: &Self, bits: usize) {
103        // Should return a BigInt, while its size is based on the abs function which is missed
104        // right now
105        unsafe { raw::TEE_BigIntShiftRight(self.0.as_mut_ptr(), op.data_ptr(), bits) };
106    }
107
108    pub fn get_bit(&self, bit_index: u32) -> bool {
109        unsafe { raw::TEE_BigIntGetBit(self.data_ptr(), bit_index) }
110    }
111
112    pub fn get_bit_count(&self) -> u32 {
113        unsafe { raw::TEE_BigIntGetBitCount(self.data_ptr()) }
114    }
115
116    pub fn add(op1: &Self, op2: &Self) -> Self {
117        let bits = max(Self::get_bit_count(op1), Self::get_bit_count(op2)) + 1;
118        let mut res = Self::new(bits);
119        unsafe { raw::TEE_BigIntAdd(res.0.as_mut_ptr(), op1.data_ptr(), op2.data_ptr()) };
120        res
121    }
122
123    pub fn sub(op1: &Self, op2: &Self) -> Self {
124        let bits = max(Self::get_bit_count(op1), Self::get_bit_count(op2)) + 1;
125        let mut res = Self::new(bits);
126        unsafe { raw::TEE_BigIntSub(res.0.as_mut_ptr(), op1.data_ptr(), op2.data_ptr()) };
127        res
128    }
129
130    pub fn neg(op: &Self) -> Self {
131        let mut res = Self::new(Self::get_bit_count(op));
132        unsafe { raw::TEE_BigIntNeg(res.0.as_mut_ptr(), op.data_ptr()) };
133        res
134    }
135
136    pub fn multiply(op1: &Self, op2: &Self) -> Self {
137        let bits = Self::get_bit_count(op1) + Self::get_bit_count(op2);
138        let mut res = Self::new(bits);
139        unsafe { raw::TEE_BigIntMul(res.0.as_mut_ptr(), op1.data_ptr(), op2.data_ptr()) };
140        res
141    }
142
143    pub fn square(op: &Self) -> Self {
144        let mut res = Self::new(2 * Self::get_bit_count(op));
145        unsafe { raw::TEE_BigIntSquare(res.0.as_mut_ptr(), op.data_ptr()) };
146        res
147    }
148
149    // document defines wrong size for result quotient
150    pub fn divide(op1: &Self, op2: &Self) -> (Self, Self) {
151        let q_bits = match op1.compare_big_int(op2) {
152            d if d >= 0 => max(1, Self::get_bit_count(op1) - Self::get_bit_count(op2)),
153            _ => 0,
154        };
155        let r_bits = Self::get_bit_count(op2);
156        let mut quotient = Self::new(q_bits);
157        let mut remainder = Self::new(r_bits);
158
159        unsafe {
160            raw::TEE_BigIntDiv(
161                quotient.0.as_mut_ptr(),
162                remainder.0.as_mut_ptr(),
163                op1.data_ptr(),
164                op2.data_ptr(),
165            )
166        };
167        (quotient, remainder)
168    }
169
170    pub fn module(op: &Self, n: &Self) -> Self {
171        let mut res = Self::new(Self::get_bit_count(n));
172        unsafe { raw::TEE_BigIntMod(res.0.as_mut_ptr(), op.data_ptr(), n.data_ptr()) };
173        res
174    }
175
176    pub fn add_mod(op1: &Self, op2: &Self, n: &Self) -> Self {
177        let mut res = Self::new(Self::get_bit_count(n));
178        unsafe {
179            raw::TEE_BigIntAddMod(
180                res.0.as_mut_ptr(),
181                op1.data_ptr(),
182                op2.data_ptr(),
183                n.data_ptr(),
184            )
185        };
186        res
187    }
188
189    pub fn sub_mod(op1: &Self, op2: &Self, n: &Self) -> Self {
190        let mut res = Self::new(Self::get_bit_count(n));
191        unsafe {
192            raw::TEE_BigIntSubMod(
193                res.0.as_mut_ptr(),
194                op1.data_ptr(),
195                op2.data_ptr(),
196                n.data_ptr(),
197            )
198        };
199        res
200    }
201
202    pub fn mul_mod(op1: &Self, op2: &Self, n: &Self) -> Self {
203        let mut res = Self::new(Self::get_bit_count(n));
204        unsafe {
205            raw::TEE_BigIntMulMod(
206                res.0.as_mut_ptr(),
207                op1.data_ptr(),
208                op2.data_ptr(),
209                n.data_ptr(),
210            )
211        };
212        res
213    }
214
215    pub fn square_mod(op: &Self, n: &Self) -> Self {
216        let mut res = Self::new(Self::get_bit_count(n));
217        unsafe { raw::TEE_BigIntSquareMod(res.0.as_mut_ptr(), op.data_ptr(), n.data_ptr()) };
218        res
219    }
220
221    pub fn inv_mod(op: &Self, n: &Self) -> Self {
222        let mut res = Self::new(Self::get_bit_count(n));
223        unsafe { raw::TEE_BigIntInvMod(res.0.as_mut_ptr(), op.data_ptr(), n.data_ptr()) };
224        res
225    }
226
227    pub fn relative_prime(op1: &Self, op2: &Self) -> bool {
228        unsafe { raw::TEE_BigIntRelativePrime(op1.data_ptr(), op2.data_ptr()) }
229    }
230
231    /* pub fn compute_extended_gcd(op1: &Self, op2: &Self) -> (Self, Self, Self)
232     * This function is implemented in OP-TEE, while the output size needs to be calculated based
233     * on the missing function TEE_BigIntAbs, so we do not port it yet.*/
234
235    pub fn is_probable_prime(&self, confidence_level: u32) -> i32 {
236        unsafe { raw::TEE_BigIntIsProbablePrime(self.data_ptr(), confidence_level) }
237    }
238
239    pub fn convert_from_big_int_fmm(
240        &mut self,
241        src: &BigIntFMM,
242        n: &BigInt,
243        context: BigIntFMMContext,
244    ) {
245        unsafe {
246            raw::TEE_BigIntConvertToFMM(
247                self.0.as_mut_ptr(),
248                src.data_ptr(),
249                n.data_ptr(),
250                context.data_ptr(),
251            )
252        };
253    }
254}
255
256impl fmt::Display for BigInt {
257    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
258        write!(f, "{:x?}", self.0)
259    }
260}
261
262pub struct BigIntFMMContext(Vec<BigIntFMMContextUnit>);
263
264impl BigIntFMMContext {
265    pub fn data_ptr(&self) -> *const u32 {
266        self.0.as_ptr()
267    }
268
269    fn size_in_u32(size: usize) -> usize {
270        unsafe { raw::TEE_BigIntFMMContextSizeInU32(size) }
271    }
272
273    // Globalplatform define FMMContext1 here while OP-TEE does not update yet
274    pub fn new(bits: u32, modulus: BigInt) -> Result<Self> {
275        let size: usize = Self::size_in_u32(bits as usize);
276        let mut tmp_vec: Vec<BigIntFMMContextUnit> = vec![0; size];
277        unsafe { raw::TEE_BigIntInitFMMContext(tmp_vec.as_mut_ptr(), size, modulus.data_ptr()) };
278        Ok(Self(tmp_vec))
279    }
280}
281
282pub struct BigIntFMM(Vec<BigIntFMMUnit>);
283
284impl BigIntFMM {
285    pub fn data_ptr(&self) -> *const u32 {
286        self.0.as_ptr()
287    }
288
289    fn size_in_u32(size: usize) -> usize {
290        unsafe { raw::TEE_BigIntFMMSizeInU32(size) }
291    }
292
293    pub fn new(bits: u32) -> Self {
294        let size: usize = Self::size_in_u32(bits as usize);
295        let mut tmp_vec: Vec<BigIntFMMUnit> = vec![0; size];
296        unsafe { raw::TEE_BigIntInitFMM(tmp_vec.as_mut_ptr(), size) };
297        Self(tmp_vec)
298    }
299
300    //Has to be initialized first
301    pub fn convert_from_big_int(&mut self, src: &BigInt, n: &BigInt, context: BigIntFMMContext) {
302        unsafe {
303            raw::TEE_BigIntConvertToFMM(
304                self.0.as_mut_ptr(),
305                src.data_ptr(),
306                n.data_ptr(),
307                context.data_ptr(),
308            )
309        };
310    }
311
312    //Has to be initialized first
313    pub fn compute_fmm(
314        &mut self,
315        op1: &BigIntFMM,
316        op2: &BigIntFMM,
317        n: &BigInt,
318        context: BigIntFMMContext,
319    ) {
320        unsafe {
321            raw::TEE_BigIntComputeFMM(
322                self.0.as_mut_ptr(),
323                op1.data_ptr(),
324                op2.data_ptr(),
325                n.data_ptr(),
326                context.data_ptr(),
327            )
328        };
329    }
330}
331//OP-TEE in version GP 1.1.1 does not implement function:
332//TEE_BigIntSetBit
333//TEE_BigIntAssign
334//TEE_BigIntAbs
335//TEE_BigIntExpMod