kopia lustrzana https://github.com/solokeys/solo1
signed update working
rodzic
0c461bb5d8
commit
bfa2d2830d
|
@ -100,7 +100,7 @@ int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len)
|
|||
}
|
||||
else
|
||||
{
|
||||
rcode = U2F_SW_WRONG_DATA;
|
||||
rcode = U2F_SW_WRONG_DATA;
|
||||
}
|
||||
printf1(TAG_WALLET,"Ignoring U2F request\n");
|
||||
goto end;
|
||||
|
|
|
@ -55,6 +55,7 @@ struct logtag tagtable[] = {
|
|||
{TAG_TIME,"[1;33mTIME[0m"},
|
||||
{TAG_WALLET,"[1;34mWALLET[0m"},
|
||||
{TAG_STOR,"[1;35mSTOR[0m"},
|
||||
{TAG_BOOT,"[1;36mBOOT[0m"},
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#ifndef _LOG_H
|
||||
#define _LOG_H
|
||||
|
||||
#include APP_CONFIG
|
||||
#include APP_CONFIG
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef DEBUG_LEVEL
|
||||
|
@ -55,6 +55,7 @@ typedef enum
|
|||
TAG_WALLET = (1 << 14),
|
||||
TAG_STOR = (1 << 15),
|
||||
TAG_DUMP2 = (1 << 16),
|
||||
TAG_BOOT = (1 << 17),
|
||||
|
||||
TAG_FILENO = (1<<31)
|
||||
} LOG_TAG;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
all:
|
||||
$(MAKE) -f application.mk -j8
|
||||
$(MAKE) -f application.mk -j8 solo.hex
|
||||
|
||||
boot:
|
||||
$(MAKE) -f bootloader.mk -j8
|
||||
$(MAKE) -f bootloader.mk -j8 bootloader.hex
|
||||
|
||||
clean:
|
||||
$(MAKE) -f application.mk clean
|
||||
|
@ -14,6 +14,11 @@ flash: solo.hex bootloader.hex
|
|||
STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect
|
||||
STM32_Programmer_CLI -c port=SWD -halt -d all.hex -rst
|
||||
|
||||
flashboot: solo.hex bootloader.hex
|
||||
python merge_hex.py solo.hex bootloader.hex all.hex
|
||||
STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect
|
||||
STM32_Programmer_CLI -c port=SWD -halt -d bootloader.hex -rst
|
||||
|
||||
bootloader.hex:
|
||||
echo "You need to build the bootloader first."
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ int main(int argc, char * argv[])
|
|||
// TAG_PARSE |
|
||||
// TAG_TIME|
|
||||
// TAG_DUMP|
|
||||
TAG_BOOT|
|
||||
TAG_GREEN|
|
||||
TAG_RED|
|
||||
TAG_ERR
|
||||
|
@ -134,7 +135,7 @@ int main(int argc, char * argv[])
|
|||
|
||||
usbhid_init();
|
||||
printf1(TAG_GEN,"init usb\n");
|
||||
|
||||
|
||||
ctaphid_init();
|
||||
printf1(TAG_GEN,"init ctaphid\n");
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "ctap.h"
|
||||
#include "crypto.h"
|
||||
#include "uECC.h"
|
||||
#include "u2f.h"
|
||||
|
||||
|
||||
#define PAGE_SIZE 2048
|
||||
|
@ -520,7 +521,8 @@ typedef enum
|
|||
BootDone = 0x41,
|
||||
BootCheck = 0x42,
|
||||
BootErase = 0x43,
|
||||
} WalletOperation;
|
||||
BootVersion = 0x44,
|
||||
} BootOperation;
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
@ -564,7 +566,9 @@ int bootloader_bridge(uint8_t klen, uint8_t * keyh)
|
|||
BootloaderReq * req = (BootloaderReq * )keyh;
|
||||
uint8_t payload[256];
|
||||
uint8_t hash[32];
|
||||
uint8_t * pubkey = (uint8_t*)"\x57\xe6\x80\x39\x56\x46\x2f\x0c\x95\xac\x72\x71\xf0\xbc\xe8\x2d\x67\xd0\x59\x29\x2e\x15\x22\x89\x6a\xbd\x3f\x7f\x27\xf3\xc0\xc6\xe2\xd7\x7d\x8a\x9f\xcc\x53\xc5\x91\xb2\x0c\x9c\x3b\x4e\xa4\x87\x31\x67\xb4\xa9\x4b\x0e\x8d\x06\x67\xd8\xc5\xef\x2c\x50\x4a\x55";
|
||||
uint8_t version = 1;
|
||||
|
||||
uint8_t * pubkey = (uint8_t*)"\x85\xaa\xce\xda\xd4\xb4\xd8\x0d\xf7\x0e\xe8\x91\x6d\x69\x8e\x00\x7a\x27\x40\x76\x93\x7a\x1d\x63\xb1\xcf\xe8\x22\xdd\x9f\xbc\x43\x3e\x34\x0a\x05\x9d\x8a\x9d\x72\xdc\xc2\x4b\x56\x9c\x64\x3d\xc1\x0d\x14\x64\x69\x52\x31\xd7\x54\xa3\xb6\x69\xa7\x6f\x6b\x81\x8d";
|
||||
const struct uECC_Curve_t * curve = NULL;
|
||||
|
||||
if (req->len > 255-9)
|
||||
|
@ -575,18 +579,20 @@ int bootloader_bridge(uint8_t klen, uint8_t * keyh)
|
|||
memset(payload, 0xff, sizeof(payload));
|
||||
memmove(payload, req->payload, req->len);
|
||||
|
||||
uint32_t addr = (*((uint32_t*)req->addr)) & 0xffffff;
|
||||
uint32_t addr = ((*((uint32_t*)req->addr)) & 0xffffff) | 0x8000000;
|
||||
|
||||
uint32_t * ptr = (uint32_t *)addr;
|
||||
|
||||
switch(req->op){
|
||||
case BootWrite:
|
||||
printf1(TAG_BOOT, "BootWrite: %08lx\r\n",(uint32_t)ptr);
|
||||
if ((uint32_t)ptr < APPLICATION_START_ADDR || (uint32_t)ptr >= APPLICATION_END_ADDR)
|
||||
{
|
||||
printf1(TAG_BOOT,"Bound exceeded [%08lx, %08lx]\r\n",APPLICATION_START_ADDR,APPLICATION_END_ADDR);
|
||||
return CTAP2_ERR_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
if (!has_erased)
|
||||
if (!has_erased || is_authorized_to_boot())
|
||||
{
|
||||
erase_application();
|
||||
has_erased = 1;
|
||||
|
@ -596,12 +602,15 @@ int bootloader_bridge(uint8_t klen, uint8_t * keyh)
|
|||
printf2(TAG_ERR, "Error, boot check bypassed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
flash_write((uint32_t)ptr,payload, req->len + (req->len%4));
|
||||
break;
|
||||
case BootDone:
|
||||
printf1(TAG_BOOT, "BootDone: ");
|
||||
dump_hex1(TAG_BOOT, payload, 32);
|
||||
ptr = (uint32_t *)APPLICATION_START_ADDR;
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(ptr, APPLICATION_END_ADDR-APPLICATION_START_ADDR);
|
||||
crypto_sha256_update((uint8_t*)ptr, APPLICATION_END_ADDR-APPLICATION_START_ADDR);
|
||||
crypto_sha256_final(hash);
|
||||
curve = uECC_secp256r1();
|
||||
|
||||
|
@ -620,9 +629,15 @@ int bootloader_bridge(uint8_t klen, uint8_t * keyh)
|
|||
return 0;
|
||||
break;
|
||||
case BootErase:
|
||||
printf1(TAG_BOOT, "BootErase.\r\n");
|
||||
erase_application();
|
||||
return 0;
|
||||
break;
|
||||
case BootVersion:
|
||||
printf1(TAG_BOOT, "BootVersion.\r\n");
|
||||
u2f_response_writeback(&version,1);
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return CTAP1_ERR_INVALID_COMMAND;
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ _Min_Stack_Size = 0x400; /* required amount of stack */
|
|||
MEMORY
|
||||
{
|
||||
/* First 32 KB is bootloader */
|
||||
/*FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 238K-8 [> Leave out 18 Kb at end for data <]*/
|
||||
FLASH (rx) : ORIGIN = 0x08008000, LENGTH = 206K-8 /* Leave out 18 Kb at end for data */
|
||||
/*FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 238K-8 [> Leave out 38 Kb at end for data <]*/
|
||||
FLASH (rx) : ORIGIN = 0x08008000, LENGTH = 186K-8 /* Leave out 38 Kb at end for data */
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
|
||||
SRAM2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -16,6 +16,8 @@ from ecdsa import SigningKey, NIST256p
|
|||
|
||||
import socket,json,base64,ssl,array,binascii
|
||||
|
||||
from sign_firmware import *
|
||||
|
||||
httpport = 8080
|
||||
udpport = 8111
|
||||
|
||||
|
@ -41,16 +43,7 @@ if __name__ == '__main__':
|
|||
print(e)
|
||||
|
||||
|
||||
def to_websafe(data):
|
||||
data = data.replace('+','-')
|
||||
data = data.replace('/','_')
|
||||
data = data.replace('=','')
|
||||
return data
|
||||
|
||||
def from_websafe(data):
|
||||
data = data.replace('-','+')
|
||||
data = data.replace('_','/')
|
||||
return data + '=='[:(3*len(data)) % 4]
|
||||
|
||||
def write(data):
|
||||
msg = from_websafe(data)
|
||||
|
@ -81,38 +74,6 @@ def read():
|
|||
msg = to_websafe(pkt)
|
||||
return msg
|
||||
|
||||
def get_firmware_object():
|
||||
sk = SigningKey.from_pem(open("signing_key.pem").read())
|
||||
h = open(HEX_FILE,'r').read()
|
||||
h = base64.b64encode(h.encode())
|
||||
h = to_websafe(h.decode())
|
||||
|
||||
num_pages = 64
|
||||
START = 0x4000
|
||||
END = 2048 * (num_pages - 3) - 4
|
||||
|
||||
ih = IntelHex(HEX_FILE)
|
||||
segs = ih.segments()
|
||||
arr = ih.tobinarray(start = START, size = END-START)
|
||||
|
||||
im_size = END-START
|
||||
|
||||
print('im_size: ', im_size)
|
||||
print('firmware_size: ', len(arr))
|
||||
|
||||
byts = (arr).tobytes() if hasattr(arr,'tobytes') else (arr).tostring()
|
||||
sig = sha256(byts)
|
||||
print('hash', binascii.hexlify(sig))
|
||||
sig = sk.sign_digest(sig)
|
||||
|
||||
print('sig', binascii.hexlify(sig))
|
||||
|
||||
sig = base64.b64encode(sig)
|
||||
sig = to_websafe(sig.decode())
|
||||
|
||||
#msg = {'data': read()}
|
||||
msg = {'firmware': h, 'signature':sig}
|
||||
return msg
|
||||
class UDPBridge(BaseHTTPRequestHandler):
|
||||
def end_headers (self):
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
|
@ -147,7 +108,7 @@ class UDPBridge(BaseHTTPRequestHandler):
|
|||
self.send_response(200)
|
||||
self.send_header('Content-type','text/json')
|
||||
|
||||
msg = get_firmware_object()
|
||||
msg = get_firmware_object("signing_key.pem",HEX_FILE)
|
||||
|
||||
self.end_headers()
|
||||
|
||||
|
@ -162,7 +123,7 @@ try:
|
|||
certfile='../web/localhost.crt', server_side=True)
|
||||
|
||||
print('Saving signed firmware to firmware.json')
|
||||
msg = get_firmware_object()
|
||||
msg = get_firmware_object("signing_key.pem",HEX_FILE)
|
||||
wfile = open('firmware.json','wb+')
|
||||
wfile.write(json.dumps(msg).encode())
|
||||
wfile.close()
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
import sys
|
||||
import json,base64,array,binascii
|
||||
from hashlib import sha256
|
||||
|
||||
from ecdsa import SigningKey, NIST256p
|
||||
from intelhex import IntelHex
|
||||
|
||||
def to_websafe(data):
|
||||
data = data.replace('+','-')
|
||||
data = data.replace('/','_')
|
||||
data = data.replace('=','')
|
||||
return data
|
||||
|
||||
def from_websafe(data):
|
||||
data = data.replace('-','+')
|
||||
data = data.replace('_','/')
|
||||
return data + '=='[:(3*len(data)) % 4]
|
||||
|
||||
def get_firmware_object(sk_name, hex_file):
|
||||
sk = SigningKey.from_pem(open(sk_name).read())
|
||||
fw = open(hex_file,'r').read()
|
||||
fw = base64.b64encode(fw.encode())
|
||||
fw = to_websafe(fw.decode())
|
||||
|
||||
START = 0x08008000
|
||||
END = START + 1024 * 186 - 8
|
||||
|
||||
ih = IntelHex(hex_file)
|
||||
segs = ih.segments()
|
||||
arr = ih.tobinarray(start = START, size = END-START)
|
||||
|
||||
im_size = END-START
|
||||
|
||||
print('im_size: ', im_size)
|
||||
print('firmware_size: ', len(arr))
|
||||
|
||||
byts = (arr).tobytes() if hasattr(arr,'tobytes') else (arr).tostring()
|
||||
h = sha256()
|
||||
h.update(byts)
|
||||
sig = binascii.unhexlify(h.hexdigest())
|
||||
print('hash', binascii.hexlify(sig))
|
||||
sig = sk.sign_digest(sig)
|
||||
|
||||
print('sig', binascii.hexlify(sig))
|
||||
|
||||
sig = base64.b64encode(sig)
|
||||
sig = to_websafe(sig.decode())
|
||||
|
||||
#msg = {'data': read()}
|
||||
msg = {'firmware': fw, 'signature':sig}
|
||||
return msg
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) != 4:
|
||||
print('usage: %s <signing-key.pem> <app.hex> <output.json>' % sys.argv[0])
|
||||
msg = get_firmware_object(sys.argv[1],sys.argv[2])
|
||||
print('Saving signed firmware to firmware.json')
|
||||
wfile = open(sys.argv[3],'wb+')
|
||||
wfile.write(json.dumps(msg).encode())
|
||||
wfile.close()
|
||||
|
||||
|
|
@ -174,12 +174,12 @@ function toUTF8Array(str) {
|
|||
var charcode = str.charCodeAt(i);
|
||||
if (charcode < 0x80) utf8.push(charcode);
|
||||
else if (charcode < 0x800) {
|
||||
utf8.push(0xc0 | (charcode >> 6),
|
||||
utf8.push(0xc0 | (charcode >> 6),
|
||||
0x80 | (charcode & 0x3f));
|
||||
}
|
||||
else if (charcode < 0xd800 || charcode >= 0xe000) {
|
||||
utf8.push(0xe0 | (charcode >> 12),
|
||||
0x80 | ((charcode>>6) & 0x3f),
|
||||
utf8.push(0xe0 | (charcode >> 12),
|
||||
0x80 | ((charcode>>6) & 0x3f),
|
||||
0x80 | (charcode & 0x3f));
|
||||
}
|
||||
// surrogate pair
|
||||
|
@ -190,9 +190,9 @@ function toUTF8Array(str) {
|
|||
// 20 bits of 0x0-0xFFFFF into two halves
|
||||
charcode = 0x10000 + (((charcode & 0x3ff)<<10)
|
||||
| (str.charCodeAt(i) & 0x3ff));
|
||||
utf8.push(0xf0 | (charcode >>18),
|
||||
0x80 | ((charcode>>12) & 0x3f),
|
||||
0x80 | ((charcode>>6) & 0x3f),
|
||||
utf8.push(0xf0 | (charcode >>18),
|
||||
0x80 | ((charcode>>12) & 0x3f),
|
||||
0x80 | ((charcode>>6) & 0x3f),
|
||||
0x80 | (charcode & 0x3f));
|
||||
}
|
||||
}
|
||||
|
@ -386,9 +386,9 @@ function send_msg_u2f(data, func, timeout) {
|
|||
appId: appid
|
||||
};
|
||||
|
||||
|
||||
console.log('sign attempt');
|
||||
window.u2f.sign(appid,chal,[key], function(res){
|
||||
|
||||
console.log('res',res);
|
||||
var d2 = new Date();
|
||||
t2 = d2.getTime();
|
||||
if (!res.signatureData)
|
||||
|
@ -410,9 +410,6 @@ if (DEVELOPMENT) {
|
|||
function formatBootRequest(cmd, addr, data) {
|
||||
var array = new Uint8Array(255);
|
||||
|
||||
if (addr == undefined)
|
||||
addr = 0x8000;
|
||||
|
||||
data = data || new Uint8Array(1);
|
||||
|
||||
if (data.length > (255 - 9)) {
|
||||
|
@ -1078,14 +1075,19 @@ async function handleFirmware(files)
|
|||
var blocks = MemoryMap.fromHex(resp.firmware);
|
||||
var addresses = blocks.keys();
|
||||
|
||||
console.log(blocks);
|
||||
console.log(addresses);
|
||||
var addr = addresses.next();
|
||||
var chunk_size = 244;
|
||||
var chunk_size = 240;
|
||||
while(!addr.done) {
|
||||
var data = blocks.get(addr.value);
|
||||
var i;
|
||||
for (i = 0; i < data.length; i += chunk_size) {
|
||||
var chunk = data.slice(i,i+chunk_size);
|
||||
console.log('addr ',addr.value + i);
|
||||
p = await dev.bootloader_write(addr.value + i, chunk);
|
||||
|
||||
console.log('writing',p);
|
||||
TEST(p.status == 'CTAP1_SUCCESS', 'Device wrote data');
|
||||
var progress = (((i/data.length) * 100 * 100) | 0)/100;
|
||||
document.getElementById('progress').textContent = ''+progress+' %';
|
||||
|
@ -1501,4 +1503,3 @@ var test;
|
|||
EC = elliptic.ec
|
||||
|
||||
//run_tests()
|
||||
|
||||
|
|
|
@ -1,202 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Directories
|
||||
cur=`pwd`
|
||||
tmp=`mktemp -d`
|
||||
scriptName=`basename $0`
|
||||
|
||||
# Certificate Variables
|
||||
OUTPATH="./"
|
||||
VERBOSE=0
|
||||
DURATION=3650 # 10 years
|
||||
|
||||
safeExit() {
|
||||
if [ -d $tmp ]; then
|
||||
if [ $VERBOSE -eq 1 ]; then
|
||||
echo "Removing temporary directory '${tmp}'"
|
||||
fi
|
||||
rm -rf $tmp
|
||||
fi
|
||||
|
||||
trap - INT TERM EXIT
|
||||
exit
|
||||
}
|
||||
|
||||
# Help Screen
|
||||
help() {
|
||||
echo -n "${scriptName} [OPTIONS] -c=US --state=California
|
||||
|
||||
Generate self-signed TLS certificate using OpenSSL
|
||||
|
||||
Options:
|
||||
-c|--country Country Name (2 letter code)
|
||||
-s|--state State or Province Name (full name)
|
||||
-l|--locality Locality Name (eg, city)
|
||||
-o|--organization Organization Name (eg, company)
|
||||
-u|--unit Organizational Unit Name (eg, section)
|
||||
-n|--common-name Common Name (e.g. server FQDN or YOUR name)
|
||||
-e|--email Email Address
|
||||
-p|--path Path to output generated keys
|
||||
-d|--duration Validity duration of the certificate (in days)
|
||||
-h|--help Display this help and exit
|
||||
-v|--verbose Verbose output
|
||||
"
|
||||
}
|
||||
|
||||
# Test output path is valid
|
||||
testPath() {
|
||||
if [ ! -d $OUTPATH ]; then
|
||||
echo "The specified directory \"${OUTPATH}\" does not exist"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Process Arguments
|
||||
while [ "$1" != "" ]; do
|
||||
PARAM=`echo $1 | awk -F= '{print $1}'`
|
||||
VALUE=`echo $1 | awk -F= '{print $2}'`
|
||||
case $PARAM in
|
||||
-h|--help) help; safeExit ;;
|
||||
-c|--country) C=$VALUE ;;
|
||||
-s|--state) ST=$VALUE ;;
|
||||
-l|--locality) L=$VALUE ;;
|
||||
-o|--organization) O=$VALUE ;;
|
||||
-u|--unit) OU=$VALUE ;;
|
||||
-n|--common-name) CN=$VALUE ;;
|
||||
-e|--email) emailAddress=$VALUE ;;
|
||||
-p|--path) OUTPATH=$VALUE; testPath ;;
|
||||
-d|--duration) DURATION=$VALUE ;;
|
||||
-v|--verbose) VERBOSE=1 ;;
|
||||
*) echo "ERROR: unknown parameter \"$PARAM\""; help; exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Prompt for variables that were not provided in arguments
|
||||
checkVariables() {
|
||||
# Country
|
||||
if [ -z $C ]; then
|
||||
echo -n "Country Name (2 letter code) [AU]:"
|
||||
read C
|
||||
fi
|
||||
|
||||
# State
|
||||
if [ -z $ST ]; then
|
||||
echo -n "State or Province Name (full name) [Some-State]:"
|
||||
read ST
|
||||
fi
|
||||
|
||||
# Locality
|
||||
if [ -z $L ]; then
|
||||
echo -n "Locality Name (eg, city) []:"
|
||||
read L
|
||||
fi
|
||||
|
||||
# Organization
|
||||
if [ -z $O ]; then
|
||||
echo -n "Organization Name (eg, company) [Internet Widgits Pty Ltd]:"
|
||||
read O
|
||||
fi
|
||||
|
||||
# Organizational Unit
|
||||
if [ -z $OU ]; then
|
||||
echo -n "Organizational Unit Name (eg, section) []:"
|
||||
read OU
|
||||
fi
|
||||
|
||||
# Common Name
|
||||
if [ -z $CN ]; then
|
||||
echo -n "Common Name (e.g. server FQDN or YOUR name) []:"
|
||||
read CN
|
||||
fi
|
||||
|
||||
# Common Name
|
||||
if [ -z $emailAddress ]; then
|
||||
echo -n "Email Address []:"
|
||||
read emailAddress
|
||||
fi
|
||||
}
|
||||
|
||||
# Show variable values
|
||||
showVals() {
|
||||
echo "Country: ${C}";
|
||||
echo "State: ${ST}";
|
||||
echo "Locality: ${L}";
|
||||
echo "Organization: ${O}";
|
||||
echo "Organization Unit: ${OU}";
|
||||
echo "Common Name: ${CN}";
|
||||
echo "Email: ${emailAddress}";
|
||||
echo "Output Path: ${OUTPATH}";
|
||||
echo "Certificate Duration (Days): ${DURATION}";
|
||||
echo "Verbose: ${VERBOSE}";
|
||||
}
|
||||
|
||||
# Init
|
||||
init() {
|
||||
cd $tmp
|
||||
pwd
|
||||
}
|
||||
|
||||
# Cleanup
|
||||
cleanup() {
|
||||
echo "Cleaning up"
|
||||
cd $cur
|
||||
rm -rf $tmp
|
||||
}
|
||||
|
||||
buildCsrCnf() {
|
||||
cat << EOF > ${tmp}/tmp.csr.cnf
|
||||
[req]
|
||||
default_bits = 2048
|
||||
prompt = no
|
||||
default_md = sha256
|
||||
distinguished_name = dn
|
||||
|
||||
[dn]
|
||||
C=${C}
|
||||
ST=${ST}
|
||||
L=${L}
|
||||
O=${O}
|
||||
OU=${OU}
|
||||
CN=${CN}
|
||||
emailAddress=${emailAddress}
|
||||
EOF
|
||||
}
|
||||
|
||||
buildExtCnf() {
|
||||
cat << EOF > ${tmp}/v3.ext
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
||||
subjectAltName = @alt_names
|
||||
|
||||
[alt_names]
|
||||
DNS.1 = ${CN}
|
||||
EOF
|
||||
}
|
||||
|
||||
# Build TLS Certificate
|
||||
build() {
|
||||
# Santizie domain name for file name
|
||||
FILENAME=${CN/\*\./}
|
||||
# Generate CA key & crt
|
||||
openssl genrsa -out ${tmp}/tmp.key 2048
|
||||
openssl req -x509 -new -nodes -key ${tmp}/tmp.key -sha256 -days ${DURATION} -out ${OUTPATH}${FILENAME}_CA.pem -subj "/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${emailAddress}"
|
||||
|
||||
# CSR Configuration
|
||||
buildCsrCnf
|
||||
|
||||
# Create v3.ext configuration file
|
||||
buildExtCnf
|
||||
|
||||
# Server key
|
||||
openssl req -new -sha256 -nodes -out ${OUTPATH}${FILENAME}.csr -newkey rsa:2048 -keyout ${OUTPATH}${FILENAME}.key -config <( cat ${tmp}/tmp.csr.cnf )
|
||||
|
||||
# Server certificate
|
||||
openssl x509 -req -in ${OUTPATH}${FILENAME}.csr -CA ${OUTPATH}${FILENAME}_CA.pem -CAkey ${tmp}/tmp.key -CAcreateserial -out ${OUTPATH}${FILENAME}.crt -days ${DURATION} -sha256 -extfile ${tmp}/v3.ext
|
||||
}
|
||||
|
||||
checkVariables
|
||||
build
|
||||
# showVals
|
||||
safeExit
|
Ładowanie…
Reference in New Issue