blob: df22661be36614e4720d42eb14e1612d4912f8ee [file] [log] [blame]
use std::prelude::v1::*;
use std::str;
use std::time::*;
use std::untrusted::time::SystemTimeEx;
use sgx_tcrypto::*;
use sgx_types::*;
use num_bigint::BigUint;
use bit_vec::BitVec;
use yasna::models::ObjectIdentifier;
use yasna::writer::PC;
use yasna::tags::{TAG_UTCTIME, TAG_UTF8STRING};
use chrono::prelude::*;
use chrono::offset::Utc;
use chrono::Duration;
const ISSUER : &str = "MesaTEE";
const SUBJECT : &str = "MesaTEE";
pub fn gen_ecc_cert(payload: String,
prv_k: &sgx_ec256_private_t,
pub_k: &sgx_ec256_public_t,
ecc_handle: &SgxEccHandle) -> Result<(Vec<u8>, Vec<u8>), sgx_status_t> {
// Generate public key bytes since both DER will use it
let mut pub_key_bytes: Vec<u8> = vec![4];
let mut pk_gx = pub_k.gx.clone();
pk_gx.reverse();
let mut pk_gy = pub_k.gy.clone();
pk_gy.reverse();
pub_key_bytes.extend_from_slice(&pk_gx);
pub_key_bytes.extend_from_slice(&pk_gy);
// Generate Certificate DER
let cert_der = yasna::construct_der(|writer| {
writer.write_sequence(|writer| {
writer.next().write_sequence(|writer| {
// Certificate Version
writer.next().write_tagged(yasna::Tag::context(0), |writer| {
writer.write_i8(2);
});
// Certificate Serial Number (unused but required)
writer.next().write_u8(1);
// Signature Algorithm: ecdsa-with-SHA256
writer.next().write_sequence(|writer| {
writer.next().write_oid(&ObjectIdentifier::from_slice(&[1,2,840,10045,4,3,2]));
});
// Issuer: CN=MesaTEE (unused but required)
writer.next().write_sequence(|writer| {
writer.next().write_set(|writer| {
writer.next().write_sequence(|writer| {
writer.next().write_oid(&ObjectIdentifier::from_slice(&[2,5,4,3]));
writer.next().write_identifier(TAG_UTF8STRING, PC::Primitive);
writer.next().write_length(ISSUER.len());
writer.buf.extend_from_slice(ISSUER.as_bytes());
});
});
});
// Validity: Issuing/Expiring Time (unused but required)
let now = SystemTime::now();//.duration_since(UNIX_EPOCH).unwrap().as_secs();
let chrono_now: DateTime<Utc> = now.into();
let issue_ts = chrono_now.format("%y%m%d%H%M%SZ").to_string();
let expire_ts = (chrono_now + Duration::days(1)).format("%y%m%d%H%M%SZ").to_string();
writer.next().write_sequence(|writer| {
writer.next().write_identifier(TAG_UTCTIME, PC::Primitive);
writer.next().write_length(13);
writer.buf.extend_from_slice(&issue_ts.as_bytes());
writer.next().write_identifier(TAG_UTCTIME, PC::Primitive);
writer.next().write_length(13);
writer.buf.extend_from_slice(&expire_ts.as_bytes());
});
// Subject: CN=MesaTEE (unused but required)
writer.next().write_sequence(|writer| {
writer.next().write_set(|writer| {
writer.next().write_sequence(|writer| {
writer.next().write_oid(&ObjectIdentifier::from_slice(&[2,5,4,3]));
writer.next().write_identifier(TAG_UTF8STRING, PC::Primitive);
writer.next().write_length(SUBJECT.len());
writer.buf.extend_from_slice(SUBJECT.as_bytes());
});
});
});
writer.next().write_sequence(|writer| {
// Public Key Algorithm
writer.next().write_sequence(|writer| {
// id-ecPublicKey
writer.next().write_oid(&ObjectIdentifier::from_slice(&[1,2,840,10045,2,1]));
// prime256v1
writer.next().write_oid(&ObjectIdentifier::from_slice(&[1,2,840,10045,3,1,7]));
});
// Public Key
writer.next().write_bitvec(&BitVec::from_bytes(&pub_key_bytes));
});
// Certificate V3 Extension
writer.next().write_tagged(yasna::Tag::context(3), |writer| {
writer.write_sequence(|writer| {
writer.next().write_sequence(|writer| {
writer.next().write_oid(&ObjectIdentifier::from_slice(&[2,16,840,1,113730,1,13]));
writer.next().write_bytes(&payload.into_bytes());
});
});
});
});
// Signature Algorithm: ecdsa-with-SHA256
writer.next().write_sequence(|writer| {
writer.next().write_oid(&ObjectIdentifier::from_slice(&[1,2,840,10045,4,3,2]));
});
// Signature
let sig = {
let tbs = &writer.buf[4..];
ecc_handle.ecdsa_sign_slice(tbs, &prv_k).unwrap()
};
let sig_der = yasna::construct_der(|writer| {
writer.write_sequence(|writer| {
let mut sig_x = sig.x.clone();
sig_x.reverse();
let mut sig_y = sig.y.clone();
sig_y.reverse();
writer.next().write_biguint(&BigUint::from_slice(&sig_x));
writer.next().write_biguint(&BigUint::from_slice(&sig_y));
});
});
writer.next().write_bitvec(&BitVec::from_bytes(&sig_der));
});
});
// Generate Private Key DER
let key_der = yasna::construct_der(|writer| {
writer.write_sequence(|writer| {
writer.next().write_u8(0);
writer.next().write_sequence(|writer| {
writer.next().write_oid(&ObjectIdentifier::from_slice(&[1,2,840,10045,2,1]));
writer.next().write_oid(&ObjectIdentifier::from_slice(&[1,2,840,10045,3,1,7]));
});
let inner_key_der = yasna::construct_der(|writer| {
writer.write_sequence(|writer| {
writer.next().write_u8(1);
let mut prv_k_r = prv_k.r.clone();
prv_k_r.reverse();
writer.next().write_bytes(&prv_k_r);
writer.next().write_tagged(yasna::Tag::context(1), |writer| {
writer.write_bitvec(&BitVec::from_bytes(&pub_key_bytes));
});
});
});
writer.next().write_bytes(&inner_key_der);
});
});
Ok((key_der, cert_der))
}
pub fn percent_decode(orig: String) -> String {
let v:Vec<&str> = orig.split("%").collect();
let mut ret = String::new();
ret.push_str(v[0]);
if v.len() > 1 {
for s in v[1..].iter() {
ret.push(u8::from_str_radix(&s[0..2], 16).unwrap() as char);
ret.push_str(&s[2..]);
}
}
ret
}