1 /** 2 * --------- 3 * |.##> <##.| SmartCard-HSM Support Scripts 4 * |# #| 5 * |# #| Copyright (c) 2011-2012 CardContact Software & System Consulting 6 * |'##> <##'| Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de) 7 * --------- 8 * 9 * Consult your license package for usage terms and conditions. 10 * 11 * @fileoverview Obtain a certificate from an online ca service 12 */ 13 14 load("../lib/smartcardhsm.js"); 15 load("../lib/hsmkeystore.js"); 16 17 // var url = "http://localhost:8080/se/caws"; 18 var url = "http://devnet.cardcontact.de/se/caws"; 19 20 var userPIN = new ByteString("648219", ASCII); 21 var initializationCode = new ByteString("57621880", ASCII); 22 23 print("If you are behind a web proxy, then please edit the proxy settings in requestcert.js"); 24 // java.lang.System.setProperty("http.proxyHost", "myproxy.com"); 25 // java.lang.System.setProperty("http.proxyPort", "3128"); 26 27 28 /** 29 * Creates a web service connector to access an online CA 30 * 31 * @class Class implementing a CA web service connector 32 * @constructor 33 * @param {String} url the web service endpoint 34 */ 35 function CAConnection(url) { 36 this.url = url; 37 this.soapcon = new SOAPConnection(); 38 this.verbose = true; 39 this.lastReturnCode = null; 40 } 41 42 43 44 /** 45 * Get the last return code 46 * 47 * @returns the last return code received or null if none defined 48 * @type String 49 */ 50 CAConnection.prototype.getLastReturnCode = function() { 51 return this.lastReturnCode; 52 } 53 54 55 56 /** 57 * Gets the last request 58 * 59 * @returns the last request 60 * @type XML 61 */ 62 CAConnection.prototype.getLastRequest = function() { 63 return this.request; 64 } 65 66 67 68 /** 69 * Gets the last response 70 * 71 * @returns the last response 72 * @type XML 73 */ 74 CAConnection.prototype.getLastResponse = function() { 75 return this.response; 76 } 77 78 79 80 /** 81 * Close the connector and release allocated resources 82 */ 83 CAConnection.prototype.close = function() { 84 this.soapcon.close(); 85 } 86 87 88 89 /** 90 * Request a certificate from the CA using a web service 91 * 92 * @param {ByteString} certreq the certificate request 93 * @param {String} messageID the messageID for asynchronous requests (optional) 94 * @param {String} responseURL the URL to which the asynchronous response is send (optional) 95 * @returns the new certificates 96 * @type ByteString[] 97 */ 98 CAConnection.prototype.requestCertificate = function(certreq, devicecert, commonName, eMailAddress, activationCode) { 99 100 this.lastReturnCode = null; 101 102 var soapConnection = new SOAPConnection(); 103 104 var ns = new Namespace("http://www.openscdp.org/CAService"); 105 106 var request = 107 <ns:RequestCertificate xmlns:ns={ns}> 108 <CertificateSigningRequest>{certreq.toString(BASE64)}</CertificateSigningRequest> 109 <DeviceCertificate>{devicecert.toString(BASE64)}</DeviceCertificate> 110 <CommonName>{commonName}</CommonName> 111 <eMailAddress>{eMailAddress}</eMailAddress> 112 </ns:RequestCertificate> 113 114 if (activationCode) { 115 request.eMailAddress += <ActivationCode>{activationCode}</ActivationCode>; 116 } 117 118 if (this.verbose) { 119 GPSystem.trace(request.toXMLString()); 120 } 121 122 this.request = request; 123 124 try { 125 var response = this.soapcon.call(this.url, request); 126 if (this.verbose) { 127 GPSystem.trace(response.toXMLString()); 128 } 129 } 130 catch(e) { 131 GPSystem.trace("SOAP call to " + this.url + " failed : " + e); 132 throw new GPError("CAConnection", GPError.DEVICE_ERROR, 0, "RequestCertificate failed with : " + e); 133 } 134 135 this.response = response; 136 137 var certlist = []; 138 139 this.lastReturnCode = response.ReturnCode.toString(); 140 141 if (this.lastReturnCode != "ok") { 142 return null; 143 } 144 145 GPSystem.trace("Received certificates:"); 146 for each (var c in response.Certificates.Certificate) { 147 var cert = new ByteString(c, BASE64); 148 certlist.push(cert); 149 GPSystem.trace(cert); 150 } 151 152 return certlist; 153 } 154 155 156 157 158 // Use default crypto provider 159 var crypto = new Crypto(); 160 161 // Create card access object 162 var card = new Card(_scsh3.reader); 163 164 card.reset(Card.RESET_COLD); 165 166 // Create SmartCard-HSM card service 167 var sc = new SmartCardHSM(card); 168 169 // Check if device is yet un-initialized 170 if (sc.queryUserPINStatus() == 0x6984) { 171 var page = "<html><p><b>Warning:</b></p><br/>" + 172 "<p>This is a new device that has never been initialized before.</p><br/>" + 173 "<p>If you choose to continue, then the device initialization code will be set to " + initializationCode.toString(HEX) + "</p><br/>" + 174 "<p>Please be advised, that this code can not be changed once set. The same code must be used in subsequent re-initialization of the device.</p><br/>" + 175 "<p>Press OK to continue or Cancel to abort.</p>" + 176 "</html>"; 177 var userAction = Dialog.prompt(page); 178 assert(userAction != null); 179 180 var userPIN = Dialog.prompt("Please select user PIN for SmartCard-HSM", "648219"); 181 assert(userPIN != null); 182 183 sc.initDevice(new ByteString("0001", HEX), new ByteString(userPIN, ASCII), initializationCode, 3); 184 } else { 185 var userPIN = Dialog.prompt("Please enter user PIN for SmartCard-HSM", "648219"); 186 assert(userPIN != null); 187 } 188 189 // Verify user PIN 190 sc.verifyUserPIN(new ByteString(userPIN, ASCII)); 191 192 var url = Dialog.prompt("Please enter URL of Online CA", url); 193 assert(url != null); 194 195 var label = url.match(/\w+:\/\/([\w.]+)/)[1]; 196 print("Using label \"" + label + "\" for key"); 197 198 var commonName = "Joe Doe"; 199 var commonName = Dialog.prompt("Please enter name or pseudonym for entry into the common name field of the certificate", commonName); 200 assert(commonName != null); 201 202 var eMailAddress = " joe.doe@openscdp.org"; 203 204 do { 205 var eMailAddress = Dialog.prompt("Please enter a valid e-mail address for entry into the subjectAlternativeName field of the certificate", eMailAddress); 206 assert(eMailAddress != null); 207 } while (eMailAddress.match(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+/)[0] != eMailAddress); 208 209 if (eMailAddress.length > 0) { 210 print("The CA will send an activation code to " + eMailAddress); 211 } 212 213 var hsmks = new HSMKeyStore(sc); 214 215 sc.enumerateKeys(); 216 var key = sc.getKey(label); 217 218 if (key) { 219 assert(Dialog.prompt("A key with the label " + label + " already exists. Press OK to delete the key")); 220 hsmks.deleteKey(label); 221 } 222 223 print("Generating a 2048 bit RSA key pair can take up to 60 seconds. Please wait..."); 224 var req = hsmks.generateRSAKeyPair(label, 2048); 225 226 var devAutCert = sc.readBinary(SmartCardHSM.C_DevAut); 227 228 var activationCode; 229 230 do { 231 var cacon = new CAConnection(url); 232 var certs = cacon.requestCertificate(req.getBytes(), devAutCert, commonName, eMailAddress, activationCode); 233 cacon.close(); 234 235 if (certs == null) { 236 var rc = cacon.getLastReturnCode(); 237 if (rc == "activation_code_wrong") { 238 assert(Dialog.prompt("Wrong activation code - Press OK to retry")); 239 } 240 if ((rc == "activation_code_required") || (rc == "activation_code_wrong")) { 241 activationCode = Dialog.prompt("Please check your e-mail and enter activation code", ""); 242 assert(activationCode != null); 243 } else { 244 print("Online CA returned " + cacon.getLastReturnCode()); 245 break; 246 } 247 } else { 248 var cert = new X509(certs[0]); 249 print(cert); 250 print("Received certificate from CA, now storing it on the device..."); 251 hsmks.storeEndEntityCertificate(label, cert); 252 } 253 } while (!certs); 254