Newer
Older
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <ykdef.h>
#include <ykcore.h>
#include <yubikey.h>
#include "ykpers.h"
#define REQ_RESPONSE_LENGTH 64
static int
configure_cfg(YKP_CONFIG *cfg, YK_STATUS *st, char *server_key, int slot)
{
// Generate Config
ykp_configure_version(cfg, st);
if(!ykp_configure_command(cfg, ((slot == 1) ? SLOT_CONFIG : SLOT_CONFIG2)))
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
{
fprintf(stderr,"Couldn't configure command");
return false;
}
if(!ykp_set_tktflag_CHAL_RESP(cfg, true))
{
fprintf(stderr,"Couldn't set CHAL_RESP flag");
return false;
}
if(!ykp_set_cfgflag_CHAL_HMAC(cfg, true))
{
fprintf(stderr,"Couldn't set CHAL_HMAC flag");
return false;
}
int res = ykp_HMAC_key_from_raw(cfg, server_key);
if (res) {
fprintf(stderr,"Bad HMAC key");
return false;
}
size_t key_bytes = (size_t)ykp_get_supported_key_length(cfg);
if(key_bytes != 20)
{
fprintf(stderr,"Yubikey doesn't support HMAC Challenge");
return false;
}
return true;
}
int
challenge_response(YK_KEY *yk, int slot, bool may_block, unsigned int challenge_len, const unsigned char *challenge,
unsigned char *response, int verbosity)
{
if (verbosity > 6)
{
fprintf(stdout, "Sending %i bytes HMAC challenge to slot %i\n", challenge_len, slot);
}
int yk_cmd = (slot == 1) ? SLOT_CHAL_HMAC1 : SLOT_CHAL_HMAC2;
if(! yk_challenge_response(yk, yk_cmd, may_block, challenge_len,
challenge, REQ_RESPONSE_LENGTH, response))
{
return false;
}
if(verbosity > 6)
{
unsigned char output_buf[(SHA1_MAX_BLOCK_SIZE * 2) + 1] = { 0 };
yubikey_hex_encode((char *)output_buf, (char *)response, 20);
printf("%s\n", output_buf);
}
return true;
}
int
key_init(YK_KEY **yk, YK_STATUS *st)
{
if (!yk_init()) {
return false;
}
if (!(*yk = yk_open_first_key())) {
printf("Could not open YubiKey. Is the YubiKey connected to the computer?");
return false;
}
if (!yk_get_status(*yk, st))
{
return false;
}
if (!(yk_check_firmware_version2(st)))
{
return false;
}
return true;
}
int
import_server_key(YK_KEY *yk, YK_STATUS *st, char *server_key, char *acc_code_hex, int verbosity, int slot)
{
YKP_CONFIG *cfg = ykp_alloc();
char data[1024] = {0};
int exit_code = OPENVPN_PLUGIN_FUNC_ERROR;
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
if(verbosity > 6)
{
ykp_export_config(cfg, data, 1024, YKP_FORMAT_LEGACY);
fwrite(data, 1, strlen(data), stdout);
}
if (acc_code_hex)
{
if(!yubikey_hex_p(acc_code_hex))
{
fprintf(stderr,
"Invalid access code string: %s\n",
acc_code_hex);
goto import_err;
}
unsigned int access_code_len = strlen(acc_code_hex) / 2;
access_code = calloc(access_code_len, sizeof(unsigned char));
yubikey_hex_decode(access_code, acc_code_hex, access_code_len);
ykp_set_access_code(cfg, access_code, access_code_len);
}
// Apply Config
YK_CONFIG *ycfg = NULL;
ycfg = ykp_core_config(cfg);
if (!yk_write_command(yk,
ycfg,
ykp_command(cfg),
acc_code_hex ? access_code : NULL))
{
fprintf(stderr, "Failed writing server key to YubiKey\n");
goto import_err;
}
if(verbosity > 3)
{
puts("Successfully wrote server key to YubiKey");
}
exit_code = OPENVPN_PLUGIN_FUNC_SUCCESS;
import_err:
if (cfg)
ykp_free_config(cfg);
free(access_code);
return exit_code;
}