samplecode/dcap-pckretrieval/qpl/src/lib.rs (96 lines of code) (raw):

// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License.. #![allow(non_snake_case)] extern crate sgx_types; #[macro_use] extern crate lazy_static; use std::sync::Mutex; use sgx_types::*; //const MAX_URL_LENGTH: usize = 2083; const QE3_ID_SIZE: usize = 16; const ENC_PPID_SIZE: usize = 384; const CPUSVN_SIZE: usize = 16; const PCESVN_SIZE: usize = 2; const PCEID_SIZE: usize = 2; //const FMSPC_SIZE: usize = 6; const MIN_CERT_DATA_SIZE: usize = 500; #[no_mangle] pub extern "C" fn sgx_ql_free_quote_config( p_quote_config: *mut sgx_ql_config_t, ) -> sgx_quote3_error_t { //println!("sgx_ql_free_quote_config: free {:p}", p_quote_config); if !p_quote_config.is_null() { let p_cert_data = unsafe { (*p_quote_config).p_cert_data }; if !p_cert_data.is_null() { let _s = unsafe { std::slice::from_raw_parts(p_cert_data, (*p_quote_config).cert_data_size as usize) }; drop(_s);// this is done implicitly. the explicit drop here is just for demon purpose } let _b: Box<sgx_ql_config_t> = unsafe { Box::from_raw(p_quote_config) }; drop(_b);// this is done implicitly. the explicit drop here is just for demon purpose } sgx_quote3_error_t::SGX_QL_SUCCESS } // The original sgx_ql_get_quote_config is not mt-safe. It writes to a global mutable array // `encrypted_ppid` and read from it later. // In this impl, we use a Mutex to guard the global `encrypted_ppid`. // The calling sequence is lazy_static! { static ref ENCRYPTED_PPID: Mutex<[u8;ENC_PPID_SIZE]> = Mutex::new([0;ENC_PPID_SIZE]); } #[no_mangle] pub extern "C" fn sgx_ql_get_quote_config( p_cert_id: *const sgx_ql_pck_cert_id_t, pp_quote_config: *mut *mut sgx_ql_config_t, ) -> sgx_quote3_error_t { //println!("sgx_ql_get_quote_config: {:p}", p_cert_id); if p_cert_id.is_null() || pp_quote_config.is_null() { return sgx_quote3_error_t::SGX_QL_ERROR_INVALID_PARAMETER; } if unsafe { (*p_cert_id).p_qe3_id }.is_null() || unsafe { (*p_cert_id).qe3_id_size } != QE3_ID_SIZE as u32 || unsafe { (*p_cert_id).p_platform_cpu_svn }.is_null() || unsafe { (*p_cert_id).p_platform_pce_isv_svn }.is_null() || unsafe { (*p_cert_id).crypto_suite } != PCE_ALG_RSA_OAEP_3072 { return sgx_quote3_error_t::SGX_QL_ERROR_INVALID_PARAMETER; } let encrypted_ppid: [u8; ENC_PPID_SIZE] = if !unsafe { (*p_cert_id).p_encrypted_ppid }.is_null() { if unsafe { (*p_cert_id).encrypted_ppid_size } != ENC_PPID_SIZE as u32 { return sgx_quote3_error_t::SGX_QL_ERROR_INVALID_PARAMETER; } else { let mut eppid = [0; ENC_PPID_SIZE]; unsafe { let p: *const u8 = (*p_cert_id).p_encrypted_ppid as *const u8; p.copy_to_nonoverlapping(eppid.as_mut_ptr(), ENC_PPID_SIZE); } if let Ok(mut l) = ENCRYPTED_PPID.lock() { *l = eppid; } eppid } } else { *ENCRYPTED_PPID.lock().unwrap() }; let version:sgx_ql_config_version_t = sgx_ql_config_version_t::SGX_QL_CONFIG_VERSION_1; let cert_cpu_svn:sgx_cpu_svn_t = unsafe { *(*p_cert_id).p_platform_cpu_svn }; let cert_pce_isv_svn: sgx_isv_svn_t = unsafe { *(*p_cert_id).p_platform_pce_isv_svn}; // previously we asserted enc_ppid_size = ENC_PPID_SIZE, qe3_id_size = QE3_ID_SIZE // so the sum here is smaller than MIN_CERT_DATA_SIZE. cert_data_size is MIN_CERT_DATA_SIZE let cert_data_size: uint32_t = std::cmp::max( ENC_PPID_SIZE + QE3_ID_SIZE + PCEID_SIZE + CPUSVN_SIZE + PCESVN_SIZE, MIN_CERT_DATA_SIZE) as u32; // cert data is: // ENC_PPID || PCEID || CPUSVN || PCESVN || QEID || 0x00... let pce_id: [u8;PCEID_SIZE] = unsafe { (*p_cert_id).pce_id }.to_le_bytes(); let cpu_svn: [u8; CPUSVN_SIZE] = unsafe { *(*p_cert_id).p_platform_cpu_svn }.svn; let pce_svn: [u8; PCESVN_SIZE] = unsafe { *(*p_cert_id).p_platform_pce_isv_svn}.to_le_bytes(); let qe_id: &[u8] = unsafe { std::slice::from_raw_parts((*p_cert_id).p_qe3_id, QE3_ID_SIZE) }; let mut cert_data_vec: Vec<u8> = encrypted_ppid.to_vec(); cert_data_vec.extend_from_slice(&pce_id[..]); cert_data_vec.extend_from_slice(&cpu_svn[..]); cert_data_vec.extend_from_slice(&pce_svn[..]); cert_data_vec.extend_from_slice(qe_id); cert_data_vec.resize_with(cert_data_size as usize, Default::default); let mut b = cert_data_vec.into_boxed_slice(); let p_cert_data = b.as_mut_ptr(); let _ = Box::into_raw(b); // memory leak here. let ql_config = sgx_ql_config_t { version: version, cert_cpu_svn: cert_cpu_svn, cert_pce_isv_svn: cert_pce_isv_svn, cert_data_size: cert_data_size, p_cert_data: p_cert_data, }; let p_ret_ql_config = Box::into_raw(Box::new(ql_config)); unsafe { *pp_quote_config = p_ret_ql_config; } sgx_quote3_error_t::SGX_QL_SUCCESS }