source: murachi/esteidfirefoxplugin/common/esteid_sign.c @ 28fc3c9

Last change on this file since 28fc3c9 was 7d3ae3e, checked in by antonioaraujob <aaraujo@…>, 9 years ago

Agregados archivos fuentes del complemento esteidfirefoxplugin de Estonia para firmar electrónicamente un hash.

  • Property mode set to 100644
File size: 18.4 KB
Line 
1/*
2 * Estonian ID card plugin for web browsers
3 *
4 * Copyright (C) 2010-2011 Codeborne <info@codeborne.com>
5 *
6 * This is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This software is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19 *
20 */
21
22#include <stdlib.h>
23#include <string.h>
24
25#include <openssl/x509.h>
26#include <openssl/pem.h>
27
28#ifndef _WIN32
29#include <pthread.h>
30#include <unistd.h>
31#else
32#include <windows.h>
33#endif
34
35#define CRYPTOKI_COMPAT
36#include "pkcs11.h"
37
38#include "esteid_sign.h"
39#include "esteid_log.h"
40#include "pkcs11_errors.h"
41#include "l10n.h"
42#include "esteid_error.h"
43#include "dialogs.h"
44#include "esteid_certinfo.h"
45
46#define FAILURE 0
47#define SUCCESS 1
48
49#define BINARY_SHA1_LENGTH 20
50#define BINARY_SHA224_LENGTH 28
51#define BINARY_SHA256_LENGTH 32
52#define BINARY_SHA512_LENGTH 64
53
54CK_BYTE RSA_SHA1_DESIGNATOR_PREFIX[] = {48, 33, 48, 9, 6, 5, 43, 14, 3, 2, 26, 5, 0, 4, 20};
55CK_BYTE RSA_SHA224_DESIGNATOR_PREFIX[] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c};
56CK_BYTE RSA_SHA256_DESIGNATOR_PREFIX[] = {48, 49, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 4, 32};
57CK_BYTE RSA_SHA512_DESIGNATOR_PREFIX[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
58
59extern CK_FUNCTION_LIST_PTR fl;
60
61extern char EstEID_error[1024];
62extern int EstEID_errorCode;
63
64#ifdef _WIN32
65#define CLOSE_SESSION_AND_RETURN(_r) { if (session) { fl->C_CloseSession(session); } return (_r); }
66#else
67#define CLOSE_SESSION_AND_RETURN(_r) { if (name) free(name); if (session) { fl->C_CloseSession(session); } return FAILURE; }
68#endif
69
70#ifdef _WIN32
71#define pthread_mutex_t HANDLE
72#define pthread_cond_t HANDLE
73#endif
74
75pthread_mutex_t pinpad_thread_mutex;
76pthread_cond_t pinpad_thread_condition;
77int pinpad_thread_result;
78int pinpad_thread_completed = FALSE;
79
80int EstEID_getRemainingTries(CK_SLOT_ID slotID) {
81        CK_TOKEN_INFO tokenInfo;
82        if (EstEID_CK_failure("C_GetTokenInfo", fl->C_GetTokenInfo(slotID, &tokenInfo))) return -1;
83        EstEID_log("flags: %li (%lx)", tokenInfo.flags, tokenInfo.flags);
84        if (tokenInfo.flags & CKF_USER_PIN_LOCKED) return 0;
85        else if (tokenInfo.flags & CKF_USER_PIN_FINAL_TRY) return 1;
86        else if (tokenInfo.flags & CKF_USER_PIN_COUNT_LOW) return 2;
87        else return 3;
88}
89
90int EstEID_isPinPad(CK_SLOT_ID slotID) {
91        CK_TOKEN_INFO tokenInfo;
92        if (EstEID_CK_failure("C_GetTokenInfo", fl->C_GetTokenInfo(slotID, &tokenInfo))) return 0;
93        EstEID_log("flags: %li (%lx)", tokenInfo.flags, tokenInfo.flags);
94        if (tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) return 1;
95        else return 0;
96}
97
98
99char *EstEID_addPadding(const char *hash, unsigned int hashLength, unsigned int *paddedHashLength) {   
100        CK_BYTE *padding;
101        char *hashWithPadding;
102        int paddingLength;
103        EstEID_log("incoming digest length = %u", hashLength);
104        switch (hashLength) {
105                case BINARY_SHA1_LENGTH:
106                        EstEID_log("SHA1");
107                        padding = RSA_SHA1_DESIGNATOR_PREFIX;
108                        paddingLength = sizeof(RSA_SHA1_DESIGNATOR_PREFIX);                     
109                        break;
110                case BINARY_SHA224_LENGTH:
111                        EstEID_log("SHA224");
112                        padding = RSA_SHA224_DESIGNATOR_PREFIX;
113                        paddingLength = sizeof(RSA_SHA224_DESIGNATOR_PREFIX);
114                        break;
115                case BINARY_SHA256_LENGTH:
116                        EstEID_log("SHA256");
117                        padding = RSA_SHA256_DESIGNATOR_PREFIX;
118                        paddingLength = sizeof(RSA_SHA256_DESIGNATOR_PREFIX);
119                        break;
120                case BINARY_SHA512_LENGTH:
121                        EstEID_log("SHA512");
122                        padding = RSA_SHA512_DESIGNATOR_PREFIX;
123                        paddingLength = sizeof(RSA_SHA512_DESIGNATOR_PREFIX);
124                        break;
125                default:
126                        EstEID_log("incorrect digest length, dropping padding");
127                        *paddedHashLength = 0;
128                        return NULL;
129        }
130
131        hashWithPadding = (char *)malloc(paddingLength + hashLength);
132        memcpy(hashWithPadding, padding, paddingLength);
133        memcpy(hashWithPadding + paddingLength, hash, hashLength);
134        *paddedHashLength = paddingLength + hashLength;
135        return hashWithPadding;
136}
137
138
139THREAD_RETURN_TYPE EstEID_pinPadLogin(void* threadData) {
140#ifndef _WIN32
141        LOG_LOCATION;
142        pthread_mutex_lock(&pinpad_thread_mutex);
143        CK_SESSION_HANDLE session = ((EstEID_PINPadThreadData*)threadData)->session;
144        CK_RV loginResult = fl->C_Login(session, CKU_USER, NULL, 0);           
145        ((EstEID_PINPadThreadData*)threadData)->result = loginResult;
146
147        closePinPadModalSheet();
148        EstEID_log("modal sheet/dialog destroyed");
149
150        pinpad_thread_completed = TRUE;
151        pthread_cond_broadcast(&pinpad_thread_condition);
152
153        pthread_mutex_unlock(&pinpad_thread_mutex);
154        pthread_exit(NULL);
155#else
156        EstEID_PINPromptDataEx* pinPromptDataEx;
157        LOG_LOCATION;
158        WaitForSingleObject(pinpad_thread_mutex, INFINITE);
159        pinPromptDataEx = (EstEID_PINPromptDataEx*)threadData;
160        pinPromptDataEx->pinPromptData.promptFunction(NULL, pinPromptDataEx->name, pinPromptDataEx->message, 0, TRUE); 
161        ReleaseMutex(pinpad_thread_mutex);
162        return TRUE;
163#endif
164}
165
166void setUserCancelErrorCodeAndMessage() {
167        EstEID_log("Got user cancel");
168        sprintf(EstEID_error, "User cancelled");
169        EstEID_errorCode = ESTEID_USER_CANCEL;
170}
171
172char* EstEID_getFullNameWithPersonalCode(EstEID_Map cert) {
173        const char *surname;
174        const char *personalID;
175        const char *givenName; 
176        char *name;     
177        int nameSize = 0;
178       
179        givenName = EstEID_mapGet(cert, "givenName");
180        if (!givenName) givenName = "";
181       
182        surname = EstEID_mapGet(cert, "surname");
183        if (!surname) surname = "";
184       
185        personalID = EstEID_mapGet(cert, "serialNumber");
186        if (!personalID) personalID = "";
187
188        nameSize = strlen(givenName) + strlen(surname) + strlen(personalID) + 4;
189        name = (char *)malloc(nameSize);
190        sprintf(name,"%s %s", givenName, surname);
191        if(strlen(personalID)) {
192                strcat(name, ", ");
193                strcat(name, personalID);
194        }
195
196        return name;
197}
198
199int EstEID_RealSign(CK_SESSION_HANDLE session, char **signature, unsigned int *signatureLength, const char *hash, unsigned int hashLength, char* name) {
200        CK_OBJECT_HANDLE privateKeyHandle;
201        CK_ULONG objectCount;
202        unsigned int hashWithPaddingLength = 0;
203        char *hashWithPadding;
204        CK_MECHANISM mechanism = {CKM_RSA_PKCS, 0, 0};
205        CK_OBJECT_CLASS objectClass = CKO_PRIVATE_KEY;
206        CK_ATTRIBUTE searchAttribute = {CKA_CLASS, &objectClass, sizeof(objectClass)};
207
208        if (EstEID_CK_failure("C_FindObjectsInit", fl->C_FindObjectsInit(session, &searchAttribute, 1))) CLOSE_SESSION_AND_RETURN(FAILURE);
209
210        if (EstEID_CK_failure("C_FindObjects", fl->C_FindObjects(session, &privateKeyHandle, 1, &objectCount))) CLOSE_SESSION_AND_RETURN(FAILURE);
211        if (EstEID_CK_failure("C_FindObjectsFinal", fl->C_FindObjectsFinal(session))) CLOSE_SESSION_AND_RETURN(FAILURE);
212
213        if (objectCount == 0) CLOSE_SESSION_AND_RETURN(FAILURE); // todo ?? set error message
214
215        if (EstEID_CK_failure("C_SignInit", fl->C_SignInit(session, &mechanism, privateKeyHandle))) CLOSE_SESSION_AND_RETURN(FAILURE);
216
217        hashWithPadding = EstEID_addPadding(hash, hashLength, &hashWithPaddingLength);
218        if (hashWithPadding) { // This is additional safeguard, as digest length is checked already before calling EstEID_addPadding()
219                CK_ULONG len;
220                if (EstEID_CK_failure("C_Sign", fl->C_Sign(session, (CK_BYTE_PTR)hashWithPadding, hashWithPaddingLength, NULL, &len))) {
221                        free(hashWithPadding);
222                        CLOSE_SESSION_AND_RETURN(FAILURE);
223                }
224                *signature = (char *)malloc(len);
225                if (EstEID_CK_failure("C_Sign", fl->C_Sign(session, (CK_BYTE_PTR)hashWithPadding, hashWithPaddingLength, (CK_BYTE_PTR) * signature, &len))) {
226                        free(hashWithPadding);
227                        CLOSE_SESSION_AND_RETURN(FAILURE);
228                }
229                *signatureLength = len;
230                free(hashWithPadding);         
231        }
232
233        if (session) {
234                if (EstEID_CK_failure("C_CloseSession", fl->C_CloseSession(session))) {
235                        return FAILURE;
236                }
237        }
238
239        if(name) {
240                free(name);
241        }
242 
243        if (!hashWithPaddingLength) { // This is additional safeguard, as digest length is checked already before calling EstEID_addPadding()
244                EstEID_log("will not sign due to incorrect incoming message digest length");
245                return FAILURE;
246        }
247        EstEID_log("successfully signed");
248        return SUCCESS;
249}
250
251
252int EstEID_getSlotId(char* certId, CK_SLOT_ID* slotId) {
253        int certIndex;
254        EstEID_Certs *certs = EstEID_loadCerts();
255        EstEID_log("certs loaded");
256        if (!certs) {
257                EstEID_log("%s", EstEID_error);
258                return FALSE;
259        }
260        else if ((certIndex = EstEID_findNonRepuditionCert(certs, certId)) == NOT_FOUND) {
261                EstEID_log("card is changed");
262                return FALSE;
263        }
264        *slotId = certs->slotIDs[certIndex];
265        return TRUE;
266}
267
268
269#ifdef _WIN32
270int EstEID_sighHashWindows(char **signature, unsigned int *signatureLength, CK_SLOT_ID slotID, EstEID_Map cert, const char *hash, unsigned int hashLength, EstEID_PINPromptData pinPromptData) {
271        CK_SESSION_HANDLE session = 0L;
272        char message[1024];
273        int remainingTries = 0; 
274        CK_RV loginResult = CKR_FUNCTION_CANCELED;
275       
276        LOG_LOCATION;
277
278        if (EstEID_CK_failure("C_OpenSession", fl->C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session))) return FAILURE;
279
280        remainingTries = EstEID_getRemainingTries(slotID);
281        EstEID_log("EstEID_getRemainingTries(slotID) = %i", remainingTries);
282        if (remainingTries == -1)
283                CLOSE_SESSION_AND_RETURN(FAILURE);
284        if (!remainingTries) {
285                sprintf_s(EstEID_error, ESTEID_ERROR_SIZE, "C_Login error: %s (%li)", pkcs11_error_message(CKR_PIN_LOCKED), CKR_PIN_LOCKED);
286                CLOSE_SESSION_AND_RETURN(FAILURE);
287        }
288        if (remainingTries < 3) {
289                sprintf_s(message, 1024, "%s %i", l10n("Tries left:"), remainingTries);
290        }
291        else {
292                message[0] = 0;
293        }
294
295        loginResult = fl->C_Login(session, CKU_USER, (unsigned char *)pinPromptData.pin2, strlen(pinPromptData.pin2));
296        if(loginResult != CKR_OK) {
297                EstEID_log("loginResult = %s", pkcs11_error_message(loginResult));
298                sprintf_s(EstEID_error, 1024, "C_Login error: %s (%li)", pkcs11_error_message(loginResult), loginResult);
299                CLOSE_SESSION_AND_RETURN(loginResult);
300        }
301       
302        return EstEID_RealSign(session, signature, signatureLength, hash, hashLength, NULL);
303}
304#endif
305
306int EstEID_signHash(char **signature, unsigned int *signatureLength, CK_SLOT_ID slotID, EstEID_Map cert, const char *hash, unsigned int hashLength, EstEID_PINPromptData pinPromptData) {
307        CK_SESSION_HANDLE session = 0L;
308        CK_RV loginResult = CKR_FUNCTION_CANCELED;
309        char *name;
310        char message[1024];
311        int remainingTries = -1;
312        int attempt = 0, blocked = FALSE;
313        int isPinPad;
314#ifdef _WIN32
315        EstEID_PINPromptDataEx pinPromptDataEx;
316#endif
317
318       
319        LOG_LOCATION;
320
321        if (EstEID_CK_failure("C_OpenSession", fl->C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session))) return FAILURE;
322
323        name = EstEID_getFullNameWithPersonalCode(cert);
324
325        for (attempt = 0;; attempt++) {
326                remainingTries = EstEID_getRemainingTries(slotID);
327                if (remainingTries == -1)
328                        CLOSE_SESSION_AND_RETURN(FAILURE);
329                if (!remainingTries || blocked) {
330                        sprintf(EstEID_error, "C_Login error: %s (%li)", pkcs11_error_message(CKR_PIN_LOCKED), CKR_PIN_LOCKED);
331                        pinPromptData.alertFunction(pinPromptData.nativeWindowHandle, l10n("PIN2 blocked, cannot sign!"));
332                        CLOSE_SESSION_AND_RETURN(FAILURE);
333                }
334                if (remainingTries < 3 || attempt) {
335                        sprintf(message, "%s%s %i", (attempt ? l10n("Incorrect PIN2! ") : ""), l10n("Tries left:"), remainingTries);
336                }
337                else {
338                        message[0] = 0;
339                }
340
341                isPinPad = EstEID_isPinPad(slotID);
342                if(!isPinPad) {
343                        // Simple card reader
344                        char *pin = pinPromptData.promptFunction(pinPromptData.nativeWindowHandle, name, message, (unsigned)atoi(EstEID_mapGet(cert, "minPinLen")), isPinPad);
345                        if (!pin || strlen(pin) == 0) {
346                                if (pin) free(pin);
347                                setUserCancelErrorCodeAndMessage();
348                                CLOSE_SESSION_AND_RETURN(FAILURE);
349                        }
350                        loginResult = fl->C_Login(session, CKU_USER, (unsigned char *)pin, strlen(pin));
351                        free(pin);
352                }
353                else {
354                        // PIN pad                     
355#ifdef _WIN32
356                        EstEID_log("creating pinpad dialog UI thread");
357                        pinpad_thread_result = -1;
358                        FAIL_IF_THREAD_ERROR("CreateMutex", (pinpad_thread_mutex = CreateMutex(NULL, FALSE, NULL)));
359#else
360                        EstEID_log("creating pinpad worker thread");
361                        pinpad_thread_result = -1;
362                        FAIL_IF_PTHREAD_ERROR("pthread_mutex_init", pthread_mutex_init(&pinpad_thread_mutex, NULL));
363                        FAIL_IF_PTHREAD_ERROR("pthread_cond_init", pthread_cond_init(&pinpad_thread_condition, NULL));
364                        pthread_t pinpad_thread;
365                        EstEID_PINPadThreadData threadData;
366                        threadData.session = session;
367                        threadData.result = CKR_OK;
368#endif
369                        EstEID_log("thread launched");
370#ifdef _WIN32
371                        /*
372                        NB! Due to Firefox for Windows specific behaviour C_Login() is launched from main thread
373                        and UI code is running in separate thread if running on Windows.
374                        */
375                        pinPromptDataEx.pinPromptData = pinPromptData;
376                        pinPromptDataEx.message = message;
377                        pinPromptDataEx.name = name;
378                        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&EstEID_pinPadLogin, (LPVOID)&pinPromptDataEx, 0, NULL);
379                        loginResult = fl->C_Login(session, CKU_USER, NULL, 0);
380                        //closePinPadModalSheet();
381#else
382                        FAIL_IF_PTHREAD_ERROR("pthread_create", pthread_create(&pinpad_thread, NULL, EstEID_pinPadLogin, (void*)&threadData));
383                        pinPromptData.promptFunction(pinPromptData.nativeWindowHandle, name, message, 0, isPinPad);
384                        loginResult = threadData.result;
385#endif
386                        EstEID_log("pinpad sheet/dialog closed");                       
387                        if (loginResult == CKR_FUNCTION_CANCELED) {
388                                setUserCancelErrorCodeAndMessage();                             
389                                CLOSE_SESSION_AND_RETURN(FAILURE);
390                        }
391                }
392                EstEID_log("loginResult = %s", pkcs11_error_message(loginResult));
393                switch (loginResult) {
394                        case CKR_PIN_LOCKED:
395                                blocked = TRUE;
396                        case CKR_PIN_INCORRECT:
397                        case CKR_PIN_INVALID:
398                        case CKR_PIN_LEN_RANGE:
399                                EstEID_log("this was attempt %i, loginResult causes to run next round", attempt);
400                                continue;
401                        default:
402                                if (EstEID_CK_failure("C_Login", loginResult)) CLOSE_SESSION_AND_RETURN(FAILURE);
403                }
404                break; // Login successful - correct PIN supplied
405        }
406
407        return EstEID_RealSign(session, signature, signatureLength, hash, hashLength, name);
408}
409
410char *EstEID_base64Encode(const char *input, int length) {
411        BIO *memBio;
412        BIO *b64Bio;
413        char *b;
414        int len;
415        char *result;
416
417        LOG_LOCATION;
418
419        memBio = BIO_new(BIO_s_mem());
420        b64Bio = BIO_new(BIO_f_base64());
421        b64Bio = BIO_push(b64Bio, memBio);
422
423        BIO_write(b64Bio, input, length);
424        (void)BIO_flush(b64Bio);
425
426
427        len = BIO_get_mem_data(memBio, &b);
428        result = (char *)malloc(len + 1);
429        strncpy(result, b, len);
430        result[len] = 0;
431        BIO_free_all(b64Bio);
432        while (result[--len] == '\n') result[len] = 0;
433        return result;
434}
435
436void EstEID_logBase64(char *message, char* data, int dataLength) {
437        char *base64;
438        LOG_LOCATION;
439        base64 = EstEID_base64Encode(data, dataLength);
440        EstEID_log(message, base64);
441        free(base64);
442}
443
444char *EstEID_hex2bin(const char *hex) {
445        int binLength;
446        char *bin;
447        char *c;
448        char *h;
449        int i = 0;
450
451        LOG_LOCATION;
452       
453        binLength = strlen(hex) / 2;
454        bin = (char *)malloc(binLength);
455        c = bin;
456        h = (char *)hex;
457        while (*h) {
458                int x;
459                sscanf(h, "%2X", &x);
460                *c = x;
461                c++;
462                h += 2;
463                i++;
464        }
465        return bin;
466}
467
468int EstEID_signHashHex(char **signatureHex, CK_SLOT_ID slotID, EstEID_Map cert, const char *hashHex, EstEID_PINPromptData pinPromptData) {
469        int expectedLengthSHA1 = BINARY_SHA1_LENGTH * 2;
470        int expectedLengthSHA256 = BINARY_SHA256_LENGTH * 2;
471        int expectedLengthSHA224 = BINARY_SHA224_LENGTH * 2;
472        int expectedLengthSHA512 = BINARY_SHA512_LENGTH * 2;
473
474        int hashHexLength, result = SUCCESS;
475        char *hash, *signature;
476        unsigned int signatureLength, hashLength;
477
478        LOG_LOCATION;
479
480        hashHexLength = strlen(hashHex);
481
482        if (hashHexLength != expectedLengthSHA1 &&
483                hashHexLength != expectedLengthSHA224 &&
484                hashHexLength != expectedLengthSHA256 &&
485                hashHexLength != expectedLengthSHA512) {
486                sprintf(EstEID_error, "invalid incoming hash length: %i", hashHexLength);
487                EstEID_errorCode = ESTEID_INVALID_HASH_ERROR;
488                return FAILURE;
489        }
490        hashLength = hashHexLength / 2;
491        hash = EstEID_hex2bin(hashHex);
492        EstEID_logBase64("hash[base64] = %s", hash, hashLength);
493
494#ifdef _WIN32
495        //NB!!! error codes may mess this up, as earlier retun values were only true/false
496        if(EstEID_isPinPad(slotID)){
497                EstEID_log("pinpad detected");
498                result = EstEID_signHash(&signature, &signatureLength, slotID, cert, hash, hashLength, pinPromptData);
499        }
500        else {
501                EstEID_log("simple card reader detected");
502                result = EstEID_sighHashWindows(&signature, &signatureLength, slotID, cert, hash, hashLength, pinPromptData);
503        }
504#else
505        result = EstEID_signHash(&signature, &signatureLength, slotID, cert, hash, hashLength, pinPromptData);
506#endif
507        EstEID_log("result = %i (where failure = %i, success = %i)", result, FAILURE, SUCCESS);
508
509        if (result==SUCCESS) {
510                EstEID_logBase64("signature[base64] = %s", signature, signatureLength);
511                *signatureHex = EstEID_bin2hex(signature, signatureLength);
512                free(hash);
513                free(signature);
514                return SUCCESS;
515        }
516        else {
517                free(hash);
518                return FAILURE;
519        }
520}
521
522int EstEID_findNonRepuditionCert(EstEID_Certs *certs, const char *certId) {
523        unsigned int i = 0;
524        for (i = 0; i < certs->count; i++) {
525                EstEID_Map cert = certs->certs[i];
526                if (EstEID_mapGet(cert, "usageNonRepudiation") && !strcmp(certId, EstEID_mapGet(cert, "certHash"))) {
527                        return i;
528                }
529        }
530        return NOT_FOUND;
531}
532
533char *EstEID_sign(char *certId, char *hash, EstEID_PINPromptData pinPromptData) {       
534        char *signature = NULL;
535        int i;
536        EstEID_Certs *certs;
537       
538        EstEID_log("called, hash=%s", hash);
539
540        certs = EstEID_loadCerts();
541        EstEID_log("certs loaded");
542        if (!certs) {
543                EstEID_log("%s", EstEID_error);
544        }
545        else if ((i = EstEID_findNonRepuditionCert(certs, certId)) == NOT_FOUND) {
546                snprintf(EstEID_error, sizeof(EstEID_error) - 1, "no cert has ID: %s", certId);
547                EstEID_errorCode = ESTEID_CERT_NOT_FOUND_ERROR;
548                EstEID_error[sizeof(EstEID_error) - 1] = 0;
549                EstEID_log("%s", EstEID_error);
550        }
551        else if (EstEID_signHashHex(&signature, certs->slotIDs[i], certs->certs[i], hash, pinPromptData)) {
552                EstEID_log("signature=%s", signature);
553        }
554        else {
555                EstEID_log("%s", EstEID_error);
556        }
557        free(certId);
558        free(hash);
559        return signature;
560}
Note: See TracBrowser for help on using the repository browser.