1#!/usr/bin/perl
2use strict;
3use warnings;
4use utf8;
5
6# Core modules
7use English;
8use FindBin qw( $Bin );
9
10# CPAN modules
11use Test::More;
12use Test::Deep;
13use Test::Exception;
14
15# Project modules
16use OpenXPKI::FileUtils;
17use lib "$Bin/../lib";
18use OpenXPKI::Test;
19
20plan tests => 17;
21
22#
23# Setup env
24#
25my $oxitest = OpenXPKI::Test->new(
26    with => [ qw( TestRealms CryptoLayer ) ],
27);
28$oxitest->insert_testcerts;
29
30#
31# Tests
32#
33use_ok "OpenXPKI::Crypto::TokenManager";
34
35my $mgmt;
36lives_ok {
37    $mgmt = OpenXPKI::Crypto::TokenManager->new;
38} 'Create OpenXPKI::Crypto::TokenManager instance';
39
40## parameter checks for get_token
41my $ca_token;
42lives_and {
43    $ca_token = $mgmt->get_token ({
44       TYPE => 'certsign',
45       NAME => 'alpha-signer-2',
46       CERTIFICATE => {
47            DATA => $oxitest->certhelper_database->cert("alpha-signer-2")->data,
48            IDENTIFIER => 'ignored',
49       }
50    });
51    ok $ca_token;
52} 'Get CA token';
53
54my $default_token;
55lives_and {
56    $default_token = $mgmt->get_system_token({ TYPE => "DEFAULT" });
57    ok $default_token;
58} 'Get default token';
59
60## create PIN (128 bit == 16 byte)
61my $passwd;
62lives_and {
63    $passwd = $default_token->command({
64        COMMAND  => "create_random",
65        RANDOM_LENGTH => 16
66    });
67    ok $passwd;
68} 'Create random password';
69
70
71# TODO Should $default_token->command({COMMAND => "create_pkey"}) be replaced with "generate_key" API method (OpenXPKI::Server::API::Object)?
72
73## create DSA key
74lives_and {
75    # OpenSSL <= 1.0.1 needs a separate parameter file for DSA keys
76    my $params = $default_token->command({
77        COMMAND => "create_params",
78        TYPE    => "DSA",
79        PKEYOPT => {
80            dsa_paramgen_bits => "2048",
81        },
82    });
83    my $key = $default_token->command({
84        COMMAND => "create_pkey",
85        ENC_ALG => "AES256",
86        PASSWD  => $passwd,
87        PARAM   => $params,
88    });
89    like $key, qr/^-----BEGIN ENCRYPTED PRIVATE KEY-----/;
90} 'Create DSA key';
91
92# TODO test DSA/RSA key creation with wrong parameters (should fail if/once we use "generate_key" API method)
93# - wrong KEY_LENGTH value
94# - wrong ENC_ALG value
95
96## create EC key
97lives_and {
98    # OpenSSL <= 1.0.1 needs a separate parameter file for EC keys
99    my $params = $default_token->command({
100        COMMAND => "create_params",
101        TYPE    => "EC",
102        PKEYOPT => {
103            ec_paramgen_curve => "sect571r1",
104        },
105    });
106    my $key = $default_token->command({
107        COMMAND => "create_pkey",
108        ENC_ALG => "AES256",
109        PASSWD  => $passwd,
110        PARAM   => $params,
111    });
112    like $key, qr/^-----BEGIN ENCRYPTED PRIVATE KEY-----/;
113} 'Create EC key';
114
115
116## create RSA key
117my $rsa_key;
118lives_and {
119    $rsa_key = $default_token->command({
120        COMMAND => "create_pkey",
121        KEY_ALG => "RSA",
122        ENC_ALG => "AES256",
123        PASSWD  => $passwd,
124        PKEYOPT => {
125            rsa_keygen_bits => 2048,
126        },
127    });
128    like $rsa_key, qr/^-----BEGIN ENCRYPTED PRIVATE KEY-----/;
129} 'Create RSA key';
130
131## try to create UNSUPPORTED_ALGORITHM key
132throws_ok {
133    $default_token->command({
134        COMMAND => "create_pkey",
135        KEY_ALG => "ROT13",
136        ENC_ALG => "AES256",
137        PASSWD  => $passwd,
138    });
139} 'OpenXPKI::Exception', 'Refuse to create key with unknown algorithm';
140
141## create CSR (PKCS#10)
142my $subject = "cn=John Dö,dc=OpenXPKI,dc=org";
143die "Test string is not UTF-8 encoded" unless Encode::is_utf8($subject);
144my $csr;
145lives_and {
146    $csr = $default_token->command({
147        COMMAND => "create_pkcs10",
148        KEY     => $rsa_key,
149        PASSWD  => $passwd,
150        SUBJECT => $subject,
151    });
152    like $csr, qr/^-----BEGIN CERTIFICATE REQUEST-----/;
153} 'Create PKCS#10';
154
155## create profile
156my $cert_profile;
157use_ok "OpenXPKI::Crypto::Profile::Certificate";
158lives_and {
159    my $cert = $oxitest->certhelper_database->cert("alpha-signer-2");
160    $cert_profile = OpenXPKI::Crypto::Profile::Certificate->new(
161        TYPE  => "ENDENTITY",
162        ID    => "user_auth_enc",
163        CA    => "alpha",
164        CACERTIFICATE => {
165            DATA        => $cert->data,
166            SUBJECT     => $cert->db->{subject},
167            IDENTIFIER  => $cert->db->{identifier},
168            NOTBEFORE   => $cert->db->{notbefore},
169            NOTAFTER    => $cert->db->{notafter},
170        },
171    );
172    $cert_profile->set_serial(1);
173    $cert_profile->set_subject($subject);
174    is $cert_profile->{PROFILE}->{SUBJECT}, $subject;
175} "Create certificate profile";
176
177## create cert
178my $cert;
179lives_and {
180    $cert = $ca_token->command({
181        COMMAND => "issue_cert",
182        CSR     => $csr,
183        PROFILE => $cert_profile,
184    });
185    like $cert, qr/^-----BEGIN CERTIFICATE-----/;
186} "Issue certificate";
187
188## build the PKCS#12 file
189lives_and {
190    my $pkcs12 = $default_token->command({
191        COMMAND => "create_pkcs12",
192        PASSWD  => $passwd,
193        KEY     => $rsa_key,
194        CERT    => $cert,
195        CHAIN   => [ $cert ],
196    });
197    ok $pkcs12;
198} "Create PKCS#12";
199
200## create CRL profile
201my $crl_profile;
202use_ok "OpenXPKI::Crypto::Profile::CRL";
203lives_and {
204    $crl_profile = OpenXPKI::Crypto::Profile::CRL->new(
205        CA => "alpha",
206        VALIDITY => {
207            VALIDITYFORMAT => 'relativedate',
208            VALIDITY => "+000014",
209        },
210        CACERTIFICATE => $oxitest->certhelper_database->cert("alpha-signer-2")->data,
211    );
212    is $crl_profile->{PROFILE}->{DAYS}, 14;
213} "Create CRL profile";
214
215## otherwise test 34 fails
216$crl_profile->set_serial (23);
217
218#### issue crl...
219my $crl;
220lives_and {
221    $crl = $ca_token->command({
222        COMMAND => "issue_crl",
223        CERTLIST => [ [ 12345 ], [ 123456, time(), 'keyCompromise', time() - 60 ] ],
224        PROFILE => $crl_profile,
225    });
226    like $crl, qr/^-----BEGIN X509 CRL-----/;
227} "Create CRL";
228
229#
230# Cleanup
231#
232$oxitest->delete_testcerts;
233
2341;
235