opensc/src/tests/pintest.c

134 lines
3.0 KiB
C
Raw Normal View History

/* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>
* All rights reserved.
*
* PKCS#15 PIN code test
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "libopensc/internal.h"
#include "libopensc/opensc.h"
#include "libopensc/pkcs15.h"
#include "common/compat_getpass.h"
#include "sc-test.h"
static struct sc_pkcs15_card *p15card;
static int enum_pins(struct sc_pkcs15_object ***ret)
{
struct sc_pkcs15_object **objs;
int i, n;
n = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, NULL, 0);
if (n < 0) {
fprintf(stderr, "Error enumerating PIN codes: %s\n",
sc_strerror(n));
return 1;
}
if (n == 0) {
fprintf(stderr, "No PIN codes found!\n");
return 0;
}
Do not cast the return value of malloc(3) and calloc(3) From http://en.wikipedia.org/wiki/Malloc#Casting_and_type_safety " Casting and type safety malloc returns a void pointer (void *), which indicates that it is a pointer to a region of unknown data type. One may "cast" (see type conversion) this pointer to a specific type, as in int *ptr = (int*)malloc(10 * sizeof (int)); When using C, this is considered bad practice; it is redundant under the C standard. Moreover, putting in a cast may mask failure to include the header stdlib.h, in which the prototype for malloc is found. In the absence of a prototype for malloc, the C compiler will assume that malloc returns an int, and will issue a warning in a context such as the above, provided the error is not masked by a cast. On certain architectures and data models (such as LP64 on 64 bit systems, where long and pointers are 64 bit and int is 32 bit), this error can actually result in undefined behavior, as the implicitly declared malloc returns a 32 bit value whereas the actually defined function returns a 64 bit value. Depending on calling conventions and memory layout, this may result in stack smashing. The returned pointer need not be explicitly cast to a more specific pointer type, since ANSI C defines an implicit conversion between the void pointer type and other pointers to objects. An explicit cast of malloc's return value is sometimes performed because malloc originally returned a char *, but this cast is unnecessary in standard C code.[4][5] Omitting the cast, however, creates an incompatibility with C++, which does require it. The lack of a specific pointer type returned from malloc is type-unsafe behaviour: malloc allocates based on byte count but not on type. This distinguishes it from the C++ new operator that returns a pointer whose type relies on the operand. (see C Type Safety). " See also http://www.opensc-project.org/pipermail/opensc-devel/2010-August/014586.html git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4636 c6295689-39f2-0310-b995-f0e70906c6a9
2010-08-18 15:08:51 +00:00
objs = calloc(n, sizeof(*objs));
2015-01-28 03:45:08 +00:00
if (!objs) {
fprintf(stderr, "Not enough memory!\n");
return 1;
}
2015-02-02 23:51:04 +00:00
if (0 > sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, n)) {
fprintf(stderr, "Error enumerating PIN codes\n");
2015-04-29 21:22:29 +00:00
free(objs);
2015-02-02 23:51:04 +00:00
return 1;
}
for (i = 0; i < n; i++) {
sc_test_print_object(objs[i]);
}
*ret = objs;
return n;
}
static int ask_and_verify_pin(struct sc_pkcs15_object *pin_obj)
{
struct sc_pkcs15_auth_info *pin_info = (struct sc_pkcs15_auth_info *) pin_obj->data;
int i = 0;
char prompt[(sizeof pin_obj->label) + 30];
u8 *pass;
if (pin_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) {
printf("Skipping unblocking pin [%.*s]\n", (int) sizeof pin_obj->label, pin_obj->label);
return 0;
}
snprintf(prompt, sizeof(prompt), "Please enter PIN code [%.*s]: ",
(int) sizeof pin_obj->label, pin_obj->label);
pass = (u8 *) getpass(prompt);
2015-01-28 03:45:08 +00:00
if (SC_SUCCESS != sc_lock(card))
return 1;
i = sc_pkcs15_verify_pin(p15card, pin_obj, pass, strlen((char *) pass));
2015-01-28 03:45:08 +00:00
if (SC_SUCCESS != sc_unlock(card))
return 1;
if (i) {
if (i == SC_ERROR_PIN_CODE_INCORRECT)
fprintf(stderr,
"Incorrect PIN code (%d tries left)\n",
pin_info->tries_left);
else
fprintf(stderr,
"PIN verifying failed: %s\n",
sc_strerror(i));
return 1;
} else
printf("PIN code correct.\n");
return 0;
}
int main(int argc, char *argv[])
{
struct sc_pkcs15_object **objs = NULL;
int i, count;
i = sc_test_init(&argc, argv);
if (i < 0)
return 1;
if (card->reader->capabilities & SC_READER_CAP_PIN_PAD)
printf("Slot is capable of doing pinpad operations!\n");
printf("Looking for a PKCS#15 compatible Smart Card... ");
fflush(stdout);
2015-01-28 03:45:08 +00:00
if (SC_SUCCESS != sc_lock(card))
return 1;
i = sc_pkcs15_bind(card, NULL, &p15card);
2015-01-28 03:45:08 +00:00
if (SC_SUCCESS != sc_unlock(card))
return 1;
if (i) {
fprintf(stderr, "failed: %s\n", sc_strerror(i));
sc_test_cleanup();
return 1;
}
printf("found.\n");
printf("Enumerating PIN codes...\n");
2015-01-28 03:45:08 +00:00
if (SC_SUCCESS != sc_lock(card))
return 1;
count = enum_pins(&objs);
2015-01-28 03:45:08 +00:00
if (SC_SUCCESS != sc_unlock(card))
return 1;
if (count < 0) {
sc_pkcs15_unbind(p15card);
sc_test_cleanup();
return 1;
}
for (i = 0; i < count; i++) {
ask_and_verify_pin(objs[i]);
}
sc_pkcs15_unbind(p15card);
sc_test_cleanup();
return 0;
}