Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions core/pit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

/*
Developed by AMI Inc. & Colorado State University.
Contact person: Rakesh Podder. Email: [email protected]
*/
PIT-Cerberus Framework

## This readme will contain information about the protection in transit features added.

pit_crypto.h/.c: Contains all the encryption, decrtption, keygeneration, OTP Generation and Validation functions.
pit.h/.c: Contains locking and unlocking functions.
pit_client.h/.c: Contains C-socket to connect with server.
pit-server.py: A server to communicate.

How to run with the server:

1. Run the server first, it will wait for client to connect.
2. Build the Project-Cerberus as define in main readme.
179 changes: 179 additions & 0 deletions core/pit/pit-server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT license.
#
# Developed by AMI Inc. & Colorado State University.
# Contact person: Rakesh Podder. Email: [email protected]

from cryptography.hazmat.primitives.serialization import load_der_public_key
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey
from cryptography.hazmat.primitives.asymmetric.ec import SECP256R1
from cryptography.hazmat.primitives.asymmetric.ec import ECDH
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.serialization import KeySerializationEncryption
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

import socket

HOST = "127.0.0.1" # Standard loopback interface address (localhost)
PORT = 5572 # Port to listen on (non-privileged ports are > 1023)
SHARED_SECRET_LEN = 32
DER_LEN = 91 #length of der encoding for this message
MSG_SIZE = 128
IV_SIZE = 12
TAG_SIZE = 16
server_private_key = ec.generate_private_key(ec.SECP256R1)
server_public_key = server_private_key.public_key()
print(f"Generated: Server ECC Key Pair.")
print()
print(f"Server X value : {server_public_key.public_numbers().x}\nServer y value : {server_public_key.public_numbers().y}")
server_public_der = server_public_key.public_bytes(encoding=serialization.Encoding.DER, format=serialization.PublicFormat.SubjectPublicKeyInfo)
server_private_der = server_private_key.private_bytes(encoding=serialization.Encoding.DER, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption())

server_public_pem = server_public_key.public_bytes(encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo)
server_private_pem = server_private_key.private_bytes(encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption())
# print(server_public_der)

#Ex secret key - 2\t\xdb\x8a\xb4%D\xb3\x07\x1f\xdb\x00$\x02\xbe\xeco\xad\xbd\xc7\x8c\xe7\xad\x14\xedVLh\xecZ\x89\xcf
#server_public_der = b'0Y0\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x03B\x00\x04\xe4Mn\xcc\x83O\xc0Fm&\x9b\xb2\x7f\xb3\xdf\xb6E\xcd\xcd\x8b\x15\x02\xb3[\xac5\xc9V\xa8\x9db1\x07\xb9\xf6\x89\xc5\x9f\xb6e\x1f\x8f\x10e\xf1\x99\x0c\xb83g\x89%\x80\x1d\x1as\xef\xe2q\x91\xaf\xd1\'\xeb'

raw_client_pub_key = None;

# with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen()
print("listening")
conn, addr = s.accept()
print("accepted")

print(f"Connected by {addr}")

#Set up vars
client_public_key = None;
# data = conn.recv(5)
# print(data)
# if(data[:4] == b"lock"):
data = conn.recv(DER_LEN)
raw_client_pub_key = data
client_public_key = load_der_public_key(data)
print(f"Recived: Cerberus ECC Key Pair.")
print()
print(f"Client X value : {client_public_key.public_numbers().x}\nClient y value : {client_public_key.public_numbers().y}")

conn.sendall(server_public_der)
conn.close()
s.close()

##Start of changes
print()
print("Generating shared secret..... Successful.")
shared_secret = server_private_key.exchange(ec.ECDH(), client_public_key)

# #Encrypt a product ID, send it over
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.bind((HOST, 5574))
s2.listen()
print("listening")
conn_pid, addr_pid = s2.accept()

iv = conn_pid.recv(IV_SIZE)

PID = b"ABCDEFGHIJKLMNOP"
aes_pid = AESGCM(shared_secret)
ePID = aes_pid.encrypt(iv, PID, None)
pid_tag = ePID[-16:]
ePID = ePID[:-16]

conn_pid.sendall(ePID)
conn_pid.sendall(pid_tag)
s2.close()

##End of changes


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, 5573))
s.listen()
print("listening")
conn, addr = s.accept()
print("accepted")
print(f"Connected by {addr}")
client_otp = conn.recv(MSG_SIZE)
print(f"[DEMO]: Encrypted OTP : {client_otp}\n")
iv = conn.recv(IV_SIZE)
client_tag = conn.recv(TAG_SIZE)






aesgcm = AESGCM(shared_secret)
#16 byte tag gets appended to the encrypted data
decrypted_client_message = aesgcm.decrypt(iv, client_otp + client_tag, None)

# print(f"Is decrypted client msg same as the original otp? (should be true) {client_og_otp == decrypted_client_message}")
with open("OTP", "wb") as f:
f.write(decrypted_client_message)
#print("[DEMO(1)]: Decrypting OTP to showcase it is the same on the client and server. Original OTP is")
#os.system("cat OTP")
#print()




difference = 128 - len(client_otp)
full_message = client_otp + (b'\0' * difference)
aes_send = AESGCM(shared_secret)
ct = aes_send.encrypt(iv, full_message, None)
serv_tag = ct[-16:]
serv_encrypted_data = ct[:-16]
serv_decrypted_data_with_tag = aes_send.decrypt(iv, serv_encrypted_data + serv_tag, None)
serv_decrypted_data = serv_decrypted_data_with_tag[:-16]

#print(f"[DEMO(2)]: Performing an AES encryption of OTPs (will be used between user and server in reality)...")
#print(f"[DEMO(2)]: Server's encrypted OTPs is : {serv_encrypted_data}\n")

#print(f"[DEMO(3)]: Performing decryption on previously encrypted OTPs (will be used between user and server in reality)...")
#print(f"[DEMO(3)]: Server's decrypted OTPs (should be original OTPs) is : {serv_decrypted_data_with_tag}\n")

#print(f"[DEMO(3)]: Was the server able to encrypt OTPs and decrypt it successfully? {serv_decrypted_data_with_tag == client_otp}\n")


#print(f"[DEMO(4)]: Server (will be user in reality) sending OTPs back to client for validation...")



import os
import math
import random
import smtplib
OTP = client_otp

#otp = OTP + " is your OTP"
msg = OTP
msg = str(msg)
s = smtplib.SMTP('smtp.gmail.com', 587)
s.starttls()

s.login("[email protected]", "iobcalxelblakshq")
# emailid = input("Enter your email: ")
# print(emailid)
s.sendmail('[email protected]', emailid, msg)
# a = input("Enter Your OTP >>: ")
# if a == OTP:
# print("Verified")
# else:
# print("Please Check your OTP again")



#user_input = input()
#user_input = bytes(user_input, 'utf-8')

#conn.sendall(user_input)
conn.sendall(client_tag)
s.close()
170 changes: 170 additions & 0 deletions core/pit/pit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

/*
Developed by AMI Inc. & Colorado State University.
Contact person: Rakesh Podder. Email: [email protected]
*/

#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "crypto/ecc.h"
#include "crypto/ecc_mbedtls.h"
#include "crypto/aes_mbedtls.h"
#include "mbedtls/ecp.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/error.h"
#include "crypto/rng_mbedtls.h"
#include "pit_crypto.h"
#include <stdbool.h>
#include "pit.h"
#include <arpa/inet.h>
#include "pit_client.h"


uint8_t *shared_secret; // Global variable to store secret key;
int shared_length; // Secret Key Length;
struct ecc_private_key priv_key; // ECC Private Key;
struct ecc_public_key pub_key; // ECC Public Key;
uint8_t class_OTPs [128]; // OTP Varibale;
int state; // State of PIT Protocol;

/**
* Sets up needed variables and sets the systems state to lock.
* Exchanges keys with the server to create a secret key
* @param secret A 32-byte empty array which will be loaded with the shared secret
* @return 1 on success
*/
int pit_Lock(uint8_t *secret){

size_t keysize = (256 / 8);

int key_stat = pit_keygenstate(keysize, &priv_key, &pub_key, &state);
if(key_stat != 1){
return PIT_KEY_GEN_FAILURE;
}

struct ecc_engine_mbedtls engine;
ecc_mbedtls_init (&engine);
struct ecc_public_key pub_key_serv;
shared_length = engine.base.get_shared_secret_max_length(&engine.base, &priv_key);
shared_secret = malloc( 8 * shared_length);

uint8_t *pub_der = NULL;
size_t der_length;
engine.base.get_public_key_der (&engine.base, &pub_key, &pub_der, &der_length);

uint8_t buffer[der_length];
bzero(buffer, der_length);

keyexchangestate(pub_der, der_length, buffer);

engine.base.init_public_key(&engine.base, buffer, der_length, &pub_key_serv);
ecc_mbedtls_release (&engine);
key_stat = pit_secretkey(&priv_key, &pub_key_serv, secret, &state);

if(key_stat != 1){
return PIT_SECRET_KEY_GEN_FAILURE;
}

memcpy(shared_secret, secret, shared_length);
state = 0;
return SUCCESS;
}

/**
* Unlocks the state of the machine by validating OTP
* Creates an OTP, then encrypts it as OTPs. Sends OTPs to the server.
* Server then encrypts OTPs again, then sends it back to the client.
* Client decrypts server's message and validates OTPs against original OTP
* @return 1 on success
*/

int pit_Unlock(){
int my_state;
uint8_t unlock_aes_iv[] = {
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b
};

int product_id_size = 16;
uint8_t ePID[16];
uint8_t ePID_tag[16];
bool isValidPID = false;
printf("User initiated Unlock Request......\n");

receive_product_info(ePID, ePID_tag, product_id_size, unlock_aes_iv, sizeof(unlock_aes_iv));

int pid_status = pit_OTPvalidation(shared_secret, shared_length, unlock_aes_iv, sizeof(unlock_aes_iv), ePID_tag, ePID, sizeof(ePID), (unsigned char *)PRODUCT_ID, &isValidPID, &my_state);
if(pid_status==1)
printf("PRODUCT ID Validation Successful. pid_status is: %d\n", pid_status );
else
printf("PRODUCT ID Validation Fails. pid_status is: %d\n", pid_status );

int otp_size = 128;
uint8_t OTP_tag[16];
uint8_t OTP[otp_size];
uint8_t OTPs[otp_size];

int status = pit_OTPgen(shared_secret, shared_length, unlock_aes_iv, sizeof(unlock_aes_iv), OTP_tag, OTP, otp_size, OTPs, &my_state);
memcpy(class_OTPs, OTPs, otp_size);
if(status != 1){
return PIT_OTP_GENERATION_FAILURE;
}
printf("OTP Generation and Encryption Successful.\n");

uint8_t serv_enc[128];
uint8_t server_encrypted_message[128];
uint8_t server_tag[16];
//Send OTPs to server
send_unlock_info(OTPs, sizeof(OTPs), unlock_aes_iv, sizeof(unlock_aes_iv), OTP_tag, serv_enc, server_tag);
printf("Encrypted OTP sent to Server.\n");

bool isValid = false;
printf("Please Enter your OTP:\n");
unsigned int temp_server_encrypted_message;
scanf("%u", &temp_server_encrypted_message);
if (temp_server_encrypted_message > UINT8_MAX) {
printf("Value out of range for uint8_t.\n");
return 1;
}
*server_encrypted_message = (uint8_t)temp_server_encrypted_message;

pit_OTPvalidation(shared_secret, shared_length, unlock_aes_iv, sizeof(unlock_aes_iv), server_tag, server_encrypted_message, sizeof(server_encrypted_message), OTP, &isValid, &my_state);
if(pid_status==1)
printf("OTP Validation Successful. pid_status is: %d\n", pid_status );
else
printf("OTP Validation Fails. pid_status is: %d\n", pid_status );
exit(20); //TODO : Remove
if(isValid){
state = 7;
return SUCCESS;
}
return PIT_UNLOCK_NOT_VALID;

}

/** Gets the state of the system
* @return The numerical value of the state of the system at the moment of calling
*/
int get_state(){
return state;
}

/**
* Get the encrypted OTP (OTPs) from the system
* @param OTPs Empty buffer to hold the encrypted OTP into
* @return 1 on success
*/
int get_OTPs(uint8_t *OTPs){
memcpy(OTPs, class_OTPs, 128); //Size of OTPs is always 128
return 1;
}



Loading