#!/usr/bin/tclsh

package require pki
package require fileutil

#
# Use additions from Feature Request id 3440058
# or just comment all "fileutil::writeFile"
# commands
#

################################################
################################################
###
### Change this var if openssl is somewhere else
###
set path_to_openssl /usr/bin

##########
#
# Checking if a key is already generated (save time)
#
puts -nonewline "Creating test key if it does not exist   "
set t [clock milliseconds] ; flush stdout

set g $t
if {[file exist test_key.pem]} {
	# Parse an existing key
	set test_key [pki::pkcs::parse_key [fileutil::cat test_key.pem]]
} else {
	# Generate key
	set test_key [pki::rsa::generate 512]
	
	# Write a pem version using privkey2pem
	fileutil::writeFile test_key.pem [::pki::x509::privkey2pem $test_key]

	# Some times, after generating the key, it throws an error:
	#  Unknown hashing algorithm: unknown
	#    while executing
	#  "::pki::verify $signature $cert_req_info_saved $keylist"
	#
	# which can be avoided by reparsing the key from the converted
	# pem just by doing this:
	#
	#set test_key [pki::pkcs::parse_key [::pki::x509::privkey2pem $test_key]]
}

puts "in [format %.3f [expr ([clock milliseconds] - $t) / 1000.00]]s"

##########
#
# Create request with some data
#
puts -nonewline "Creating the request to be signed        "
set t [clock milliseconds] ; flush stdout

# Setting some data to populate the request
set dat(cn) "test"
set dat(ou) "test"
set dat(o)  "test"
set dat(l)  "Monterrey"
set dat(st) "Nuevo Leon"
set dat(c)  "MX"
set dat(email) "someone@somewhere.in.mx"
set d [list]
foreach x "c st l o ou cn" {
  lappend d $x
  lappend d $dat($x)
}

# Creating request
set test_req [::pki::pkcs::create_csr $test_key $d 1 sha1]
fileutil::writeFile test_req.pem $test_req

puts "in [format %.3f [expr ([clock milliseconds] - $t) / 1000.00]]s"

##########
#
# Checking for existing CA and its key
#   (is there a way to create a selfsigned CA with PKI package?)
#
if {![file exist ca_key.pem]} {
	puts -nonewline "CA key does not exists, creating one     "
	set t [clock milliseconds] ; flush stdout

	set o {genrsa -out ca_key.pem 4096}
	eval catch \{exec [file join $path_to_openssl openssl] $o\} e
	file delete ca_openssl.pem

	puts "in [format %.3f [expr ([clock milliseconds] - $t) / 1000.00]]s"
}
if {![file exist ca_openssl.pem]} {
	puts -nonewline "CA cert does not exists, creating one    "
	set t [clock milliseconds] ; flush stdout

	set o {req -new -x509 -extensions v3_ca -days 3650 -subj "/CN=CA ROOT/O=catest/C=MX/ST=Nuevo Leon/L=Monterrey" -out ca_openssl.pem -key ca_key.pem}
	eval catch \{exec [file join $path_to_openssl openssl] $o\} e

	puts "in [format %.3f [expr ([clock milliseconds] - $t) / 1000.00]]s"
}

##########
#
# Parsing CA and its key
#
puts -nonewline "Parsing CA and its key                   "
set t [clock milliseconds] ; flush stdout

set ca_key [pki::pkcs::parse_key [fileutil::cat ca_key.pem]]
set ca     [::pki::x509::parse_cert [fileutil::cat ca_openssl.pem]]

puts "in [format %.3f [expr ([clock milliseconds] - $t) / 1000.00]]s"

##########
#
# Signing request
#
puts -nonewline "Signing request                          "
set t [clock milliseconds] ; flush stdout

# Parsing request to tcl list style
set parsed_req [pki::pkcs::parse_csr $test_req]

# Signing the request
set ctime      [clock seconds]
set fca        [::pki::x509::create_cert $parsed_req "$ca $ca_key" 1 $ctime [clock add $ctime 3 year] 0 "" true]
fileutil::writeFile test.pem $fca

puts "in [format %.3f [expr ([clock milliseconds] - $t) / 1000.00]]s"

##########
#
# Done
#
puts "[string repeat - 50]\ndone!!                                   in [format %.3f [expr ([clock milliseconds] - $g) / 1000.00]]s"
