| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | |
|---|
| 20 | |
|---|
| 21 | #include "internal.h" |
|---|
| 22 | #include "pkcs15.h" |
|---|
| 23 | #include <stdio.h> |
|---|
| 24 | #include <stdlib.h> |
|---|
| 25 | #include <string.h> |
|---|
| 26 | #ifdef HAVE_UNISTD_H |
|---|
| 27 | #include <unistd.h> |
|---|
| 28 | #endif |
|---|
| 29 | #include <sys/stat.h> |
|---|
| 30 | #include <limits.h> |
|---|
| 31 | #include <errno.h> |
|---|
| 32 | #include <assert.h> |
|---|
| 33 | |
|---|
| 34 | static int generate_cache_filename(struct sc_pkcs15_card *p15card, |
|---|
| 35 | const sc_path_t *path, |
|---|
| 36 | char *buf, size_t bufsize) |
|---|
| 37 | { |
|---|
| 38 | char dir[PATH_MAX]; |
|---|
| 39 | char pathname[SC_MAX_PATH_SIZE*2+1]; |
|---|
| 40 | int r; |
|---|
| 41 | const u8 *pathptr; |
|---|
| 42 | size_t i, pathlen; |
|---|
| 43 | |
|---|
| 44 | if (path->type != SC_PATH_TYPE_PATH) |
|---|
| 45 | return SC_ERROR_INVALID_ARGUMENTS; |
|---|
| 46 | assert(path->len <= SC_MAX_PATH_SIZE); |
|---|
| 47 | r = sc_get_cache_dir(p15card->card->ctx, dir, sizeof(dir)); |
|---|
| 48 | if (r) |
|---|
| 49 | return r; |
|---|
| 50 | pathptr = path->value; |
|---|
| 51 | pathlen = path->len; |
|---|
| 52 | if (pathlen > 2 && memcmp(pathptr, "\x3F\x00", 2) == 0) { |
|---|
| 53 | pathptr += 2; |
|---|
| 54 | pathlen -= 2; |
|---|
| 55 | } |
|---|
| 56 | for (i = 0; i < pathlen; i++) |
|---|
| 57 | sprintf(pathname + 2*i, "%02X", pathptr[i]); |
|---|
| 58 | if (p15card->serial_number != NULL) { |
|---|
| 59 | if (p15card->last_update != NULL) |
|---|
| 60 | r = snprintf(buf, bufsize, "%s/%s_%s_%s", dir, |
|---|
| 61 | p15card->serial_number, p15card->last_update, |
|---|
| 62 | pathname); |
|---|
| 63 | else |
|---|
| 64 | r = snprintf(buf, bufsize, "%s/%s_DATE_%s", dir, |
|---|
| 65 | p15card->serial_number, pathname); |
|---|
| 66 | if (r < 0) |
|---|
| 67 | return SC_ERROR_BUFFER_TOO_SMALL; |
|---|
| 68 | } else |
|---|
| 69 | return SC_ERROR_INVALID_ARGUMENTS; |
|---|
| 70 | return SC_SUCCESS; |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card, |
|---|
| 74 | const sc_path_t *path, |
|---|
| 75 | u8 **buf, size_t *bufsize) |
|---|
| 76 | { |
|---|
| 77 | char fname[PATH_MAX]; |
|---|
| 78 | int r; |
|---|
| 79 | FILE *f; |
|---|
| 80 | size_t count, offset, got; |
|---|
| 81 | struct stat stbuf; |
|---|
| 82 | u8 *data = NULL; |
|---|
| 83 | |
|---|
| 84 | r = generate_cache_filename(p15card, path, fname, sizeof(fname)); |
|---|
| 85 | if (r != 0) |
|---|
| 86 | return r; |
|---|
| 87 | r = stat(fname, &stbuf); |
|---|
| 88 | if (r) |
|---|
| 89 | return SC_ERROR_FILE_NOT_FOUND; |
|---|
| 90 | if (path->count < 0) { |
|---|
| 91 | count = stbuf.st_size; |
|---|
| 92 | offset = 0; |
|---|
| 93 | } else { |
|---|
| 94 | count = path->count; |
|---|
| 95 | offset = path->index; |
|---|
| 96 | if (offset + count > (size_t)stbuf.st_size) |
|---|
| 97 | return SC_ERROR_FILE_NOT_FOUND; |
|---|
| 98 | } |
|---|
| 99 | if (*buf == NULL) { |
|---|
| 100 | data = (u8 *) malloc((size_t)stbuf.st_size); |
|---|
| 101 | if (data == NULL) |
|---|
| 102 | return SC_ERROR_OUT_OF_MEMORY; |
|---|
| 103 | } else |
|---|
| 104 | if (count > *bufsize) |
|---|
| 105 | return SC_ERROR_BUFFER_TOO_SMALL; |
|---|
| 106 | f = fopen(fname, "rb"); |
|---|
| 107 | if (f == NULL) { |
|---|
| 108 | if (data) |
|---|
| 109 | free(data); |
|---|
| 110 | return SC_ERROR_FILE_NOT_FOUND; |
|---|
| 111 | } |
|---|
| 112 | if (offset) |
|---|
| 113 | fseek(f, (long)offset, SEEK_SET); |
|---|
| 114 | if (data) |
|---|
| 115 | *buf = data; |
|---|
| 116 | got = fread(*buf, 1, count, f); |
|---|
| 117 | fclose(f); |
|---|
| 118 | if (got != count) { |
|---|
| 119 | if (data) |
|---|
| 120 | free(data); |
|---|
| 121 | return SC_ERROR_BUFFER_TOO_SMALL; |
|---|
| 122 | } |
|---|
| 123 | *bufsize = count; |
|---|
| 124 | if (data) |
|---|
| 125 | *buf = data; |
|---|
| 126 | return 0; |
|---|
| 127 | } |
|---|
| 128 | |
|---|
| 129 | int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card, |
|---|
| 130 | const sc_path_t *path, |
|---|
| 131 | const u8 *buf, size_t bufsize) |
|---|
| 132 | { |
|---|
| 133 | char fname[PATH_MAX]; |
|---|
| 134 | int r; |
|---|
| 135 | FILE *f; |
|---|
| 136 | size_t c; |
|---|
| 137 | |
|---|
| 138 | r = generate_cache_filename(p15card, path, fname, sizeof(fname)); |
|---|
| 139 | if (r != 0) |
|---|
| 140 | return r; |
|---|
| 141 | |
|---|
| 142 | f = fopen(fname, "wb"); |
|---|
| 143 | |
|---|
| 144 | |
|---|
| 145 | |
|---|
| 146 | if (f == NULL && errno == ENOENT) { |
|---|
| 147 | if ((r = sc_make_cache_dir(p15card->card->ctx)) < 0) |
|---|
| 148 | return r; |
|---|
| 149 | f = fopen(fname, "wb"); |
|---|
| 150 | } |
|---|
| 151 | if (f == NULL) |
|---|
| 152 | return 0; |
|---|
| 153 | |
|---|
| 154 | c = fwrite(buf, 1, bufsize, f); |
|---|
| 155 | fclose(f); |
|---|
| 156 | if (c != bufsize) { |
|---|
| 157 | sc_error(p15card->card->ctx, "fwrite() wrote only %d bytes", c); |
|---|
| 158 | unlink(fname); |
|---|
| 159 | return SC_ERROR_INTERNAL; |
|---|
| 160 | } |
|---|
| 161 | return 0; |
|---|
| 162 | } |
|---|