1 /* 2 * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "hx_locl.h" 35 #include "pkcs11.h" 36 #include <err.h> 37 38 static CK_FUNCTION_LIST_PTR func; 39 40 41 static CK_RV 42 find_object(CK_SESSION_HANDLE session, 43 char *id, 44 CK_OBJECT_CLASS key_class, 45 CK_OBJECT_HANDLE_PTR object) 46 { 47 CK_ULONG object_count; 48 CK_RV ret; 49 CK_ATTRIBUTE search_data[] = { 50 {CKA_ID, id, 0 }, 51 {CKA_CLASS, &key_class, sizeof(key_class)} 52 }; 53 CK_ULONG num_search_data = sizeof(search_data)/sizeof(search_data[0]); 54 55 search_data[0].ulValueLen = strlen(id); 56 57 ret = (*func->C_FindObjectsInit)(session, search_data, num_search_data); 58 if (ret != CKR_OK) 59 return ret; 60 61 ret = (*func->C_FindObjects)(session, object, 1, &object_count); 62 if (ret != CKR_OK) 63 return ret; 64 if (object_count == 0) { 65 printf("found no object\n"); 66 return 1; 67 } 68 69 ret = (*func->C_FindObjectsFinal)(session); 70 if (ret != CKR_OK) 71 return ret; 72 73 return CKR_OK; 74 } 75 76 static char *sighash = "hej"; 77 static char signature[1024]; 78 79 80 int 81 main(int argc, char **argv) 82 { 83 CK_SLOT_ID_PTR slot_ids; 84 CK_SLOT_ID slot; 85 CK_ULONG num_slots; 86 CK_RV ret; 87 CK_SLOT_INFO slot_info; 88 CK_TOKEN_INFO token_info; 89 CK_SESSION_HANDLE session; 90 CK_OBJECT_HANDLE public, private; 91 92 ret = C_GetFunctionList(&func); 93 if (ret != CKR_OK) 94 errx(1, "C_GetFunctionList failed: %d", (int)ret); 95 96 (*func->C_Initialize)(NULL_PTR); 97 98 ret = (*func->C_GetSlotList)(FALSE, NULL, &num_slots); 99 if (ret != CKR_OK) 100 errx(1, "C_GetSlotList1 failed: %d", (int)ret); 101 102 if (num_slots == 0) 103 errx(1, "no slots"); 104 105 if ((slot_ids = calloc(1, num_slots * sizeof(*slot_ids))) == NULL) 106 err(1, "alloc slots failed"); 107 108 ret = (*func->C_GetSlotList)(FALSE, slot_ids, &num_slots); 109 if (ret != CKR_OK) 110 errx(1, "C_GetSlotList2 failed: %d", (int)ret); 111 112 slot = slot_ids[0]; 113 free(slot_ids); 114 115 ret = (*func->C_GetSlotInfo)(slot, &slot_info); 116 if (ret) 117 errx(1, "C_GetSlotInfo failed: %d", (int)ret); 118 119 if ((slot_info.flags & CKF_TOKEN_PRESENT) == 0) 120 errx(1, "no token present"); 121 122 ret = (*func->C_OpenSession)(slot, CKF_SERIAL_SESSION, 123 NULL, NULL, &session); 124 if (ret != CKR_OK) 125 errx(1, "C_OpenSession failed: %d", (int)ret); 126 127 ret = (*func->C_GetTokenInfo)(slot, &token_info); 128 if (ret) 129 errx(1, "C_GetTokenInfo1 failed: %d", (int)ret); 130 131 if (token_info.flags & CKF_LOGIN_REQUIRED) { 132 ret = (*func->C_Login)(session, CKU_USER, 133 (unsigned char*)"foobar", 6); 134 if (ret != CKR_OK) 135 errx(1, "C_Login failed: %d", (int)ret); 136 } 137 138 ret = (*func->C_GetTokenInfo)(slot, &token_info); 139 if (ret) 140 errx(1, "C_GetTokenInfo2 failed: %d", (int)ret); 141 142 if (token_info.flags & CKF_LOGIN_REQUIRED) 143 errx(1, "login required, even after C_Login"); 144 145 ret = find_object(session, "cert", CKO_PUBLIC_KEY, &public); 146 if (ret != CKR_OK) 147 errx(1, "find cert failed: %d", (int)ret); 148 ret = find_object(session, "cert", CKO_PRIVATE_KEY, &private); 149 if (ret != CKR_OK) 150 errx(1, "find private key failed: %d", (int)ret); 151 152 { 153 CK_ULONG ck_sigsize; 154 CK_MECHANISM mechanism; 155 156 memset(&mechanism, 0, sizeof(mechanism)); 157 mechanism.mechanism = CKM_RSA_PKCS; 158 159 ret = (*func->C_SignInit)(session, &mechanism, private); 160 if (ret != CKR_OK) 161 return 1; 162 163 ck_sigsize = sizeof(signature); 164 ret = (*func->C_Sign)(session, (CK_BYTE *)sighash, strlen(sighash), 165 (CK_BYTE *)signature, &ck_sigsize); 166 if (ret != CKR_OK) { 167 printf("C_Sign failed with: %d\n", (int)ret); 168 return 1; 169 } 170 171 ret = (*func->C_VerifyInit)(session, &mechanism, public); 172 if (ret != CKR_OK) 173 return 1; 174 175 ret = (*func->C_Verify)(session, (CK_BYTE *)signature, ck_sigsize, 176 (CK_BYTE *)sighash, strlen(sighash)); 177 if (ret != CKR_OK) { 178 printf("message: %d\n", (int)ret); 179 return 1; 180 } 181 } 182 183 #if 0 184 { 185 CK_ULONG ck_sigsize, outsize; 186 CK_MECHANISM mechanism; 187 char outdata[1024]; 188 189 memset(&mechanism, 0, sizeof(mechanism)); 190 mechanism.mechanism = CKM_RSA_PKCS; 191 192 ret = (*func->C_EncryptInit)(session, &mechanism, public); 193 if (ret != CKR_OK) 194 return 1; 195 196 ck_sigsize = sizeof(signature); 197 ret = (*func->C_Encrypt)(session, (CK_BYTE *)sighash, strlen(sighash), 198 (CK_BYTE *)signature, &ck_sigsize); 199 if (ret != CKR_OK) { 200 printf("message: %d\n", (int)ret); 201 return 1; 202 } 203 204 ret = (*func->C_DecryptInit)(session, &mechanism, private); 205 if (ret != CKR_OK) 206 return 1; 207 208 outsize = sizeof(outdata); 209 ret = (*func->C_Decrypt)(session, (CK_BYTE *)signature, ck_sigsize, 210 (CK_BYTE *)outdata, &outsize); 211 if (ret != CKR_OK) { 212 printf("message: %d\n", (int)ret); 213 return 1; 214 } 215 216 if (ct_memcmp(sighash, outdata, strlen(sighash)) != 0) 217 return 1; 218 } 219 #endif 220 221 ret = (*func->C_CloseSession)(session); 222 if (ret != CKR_OK) 223 return 1; 224 225 (*func->C_Finalize)(NULL_PTR); 226 227 return 0; 228 } 229