#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define KEY_SIZE_BYTES 16 /* maximum length for a key */ #define KEY_SIZE_BITS 128 /* 128-bits AES key */ /**************************************************************************************** void bin2hex (unsigned char*, char*, size_t) Converts an array of binary data into a hexidecimal string Parameters: unsigned char* dp - pointer to data array, of length dlen char* hp - pointer to buffer to store hex value, of length 2*dlen+1 size_t dlen - the size of *dp ****************************************************************************************/ void bin2hex(const unsigned char* dp, char* hp, const size_t dlen) { static const char htable[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; unsigned int i; for (i=0; i>4) & 0x0f]; hp[2*i+1] = htable[(dp[i]) & 0x0f]; } hp[2*dlen] = '\0'; } /**************************************************************************************** void hex2bin (char *, unsigned char*) Converts a hexidecimal string into an array of binary data Parameters: char* hp - pointer to null terminated hexadecimal string unsigned char* dp - pointer to binary array ****************************************************************************************/ void hex2bin(const char* dp, unsigned char* hp) { while (*dp != 0) { sscanf(dp,"%2x", hp); dp +=2; hp++; } } /**************************************************************************************** char * my_get_pin (int, char *, int) Reads a pin from a file, when the pin is in the clear is will be encrypted using AES-128-CBC and written back to the file. Structure of the engine_pkcs11.ini file: # # PIN for SafeNet HSM, used by adapted version of engine_pkcs11.ini # the pin can be entered in the clear and will be encrypted on first usage. # Maximum PIN length is 12 characters. # The line with PIN_= must be the last of the file. # # e.g. for the pin of slot 0: # PIN_0=12345 After the first run the last line will be replaced by: PIN_0=encrypted:07e1304d5ca47da24c174a547d133194 Parameters: int slot_nr - the slotnumber of the HSM for which the PIN is retrieved char* sc_pin - pointer to an array where the pin will be stored int maxlen - maximum length of the pin. ****************************************************************************************/ char *my_get_pin(int slot_nr, char *pin, int maxlen) { char filename[1024] = "engine_pkcs11.ini"; unsigned char key[KEY_SIZE_BYTES] = {0xC7, 0x4A, 0x4B, 0x84, 0xFE, 0xA3, 0x8B, 0xA7, 0x0F, 0xB6, 0x41, 0x3B, 0xC4, 0x6D, 0x88, 0x09}; unsigned char encrypted[2048]; size_t encrypted_len = 2048; char decrypted[2048]; char * encrypted_hex = NULL; FILE* fp; char pbuf[2048]; char pinline[2048]; int found = 0; fpos_t position; AES_KEY ctx; unsigned char iv[AES_BLOCK_SIZE]; char search[128]; char *remaining_of_file = NULL; long remaining_size = 0; char windir[256]; /* set the IV of the AES-128-CBC to all 0s */ memset(iv, 0, 16); /* open the PIN file */ fp = fopen(filename, "r+"); if (fp == NULL) { /* if not found in our own directory, then look in the windows directory */ GetWindowsDirectory(windir, 128); strcat (windir, "\\engine_pkcs11.ini"); fp = fopen (windir, "r+"); if (fp == NULL) { fprintf (stderr, "Unable to open engine_pkcs11.ini\n"); return NULL; } } /* define the search string, including the slotnumber */ sprintf(search, "PIN_%d=", slot_nr); while (!found && !feof(fp)) { fgetpos(fp, &position); fgets(pbuf, 2048, fp); if (strncmp(pbuf, search, strlen(search)) == 0) { strcpy(pinline, pbuf + strlen(search)); found = 1; } } if (!found) { fprintf (stderr, "No pinline, PIN_= found for slotnr<%d> in engine_pkcs11.ini\n", slot_nr); return NULL; } /* remove the trailing newline's and cr's */ while ((pinline[strlen(pinline) - 1] == '\n') || (pinline[strlen(pinline) - 1] == '\r')) { pinline[strlen(pinline) - 1] = 0; } if (strncmp(pinline, "encrypted:", 10) != 0) { /* The pin is in the clear, */ /* return the clear pin */ strcpy(pin, pinline); /* set up the AES key structure */ AES_set_encrypt_key(key, KEY_SIZE_BITS, &ctx); /* encrypt the pin using AES-128-CBC */ AES_cbc_encrypt((unsigned char *)pinline, encrypted, AES_BLOCK_SIZE, &ctx, iv, AES_ENCRYPT); /* convert the binary encrypted pin to a hex string */ encrypted_hex = (char *)malloc(2*AES_BLOCK_SIZE + 1); bin2hex(encrypted, encrypted_hex, AES_BLOCK_SIZE); /* write back the pin to the ini file, the position was already stored */ /* first read in the remaining of the file to write back */ remaining_of_file = (char *)malloc(2048); remaining_size = fread((void *)remaining_of_file, 1, 2048, fp); if (fsetpos(fp, &position) != 0) { fprintf (stderr, "Unable to set the position in engine_pkcs11.ini\n"); return NULL; } strcpy(pinline, search); strcat(pinline, "encrypted:"); strcat(pinline, encrypted_hex); strcat(pinline,"\n"); fputs(pinline, fp); /* and write back the remaining part */ fwrite(remaining_of_file, 1, remaining_size, fp); } else { /* The pin is already encrypted in the file. /* skip the "encrypted:" string */ strcpy(pinline, pinline+10); /* convert the hex string back to the binary encrypted data */ hex2bin(pinline, encrypted); /* set up the AES key structure */ AES_set_decrypt_key(key, KEY_SIZE_BITS, &ctx); /* decrypts the pin using AES-128-CBC */ AES_cbc_encrypt(encrypted, (unsigned char *)decrypted, AES_BLOCK_SIZE, &ctx, iv, AES_DECRYPT); /* return the decrypted pin */ strcpy(pin, decrypted); } /* clean up */ if (encrypted_hex != NULL) { free((void *)encrypted_hex); } if (remaining_of_file != NULL) { free((void *)remaining_of_file); } if (fp != NULL) { fclose(fp); fp = NULL; } return pin; }