Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C_OpenSession fails with compressed certificates on device #93

Closed
dwmw2 opened this issue Oct 1, 2016 · 8 comments
Closed

C_OpenSession fails with compressed certificates on device #93

dwmw2 opened this issue Oct 1, 2016 · 8 comments

Comments

@dwmw2
Copy link

dwmw2 commented Oct 1, 2016

After I fix #91 it fails at the next hurdle (too):

$ sudo PKCS11SPY=`pwd`/ykcs11/.libs/libykcs11.so  p11tool --list-tokens --provider=/usr/lib64/pkcs11-spy.so 


*************** OpenSC PKCS#11 spy *****************
debug: ykcs11.c:171 (C_GetFunctionList): In
debug: ykcs11.c:179 (C_GetFunctionList): Out
Loaded: "/home/dwmw2/git/yubico-piv-tool/ykcs11/.libs/libykcs11.so"

0: C_GetFunctionList
2016-10-01 23:07:46.914
Returned:  0 CKR_OK

1: C_Initialize
2016-10-01 23:07:46.915
[in] pInitArgs = 0x564fe35c3d20
     flags: 2
       CKF_OS_LOCKING_OK
debug: ykcs11.c:86 (C_Initialize): In
trying to connect to reader 'Yubico Yubikey NEO OTP+CCID 00 00'.
debug: ykcs11.c:104 (C_Initialize): Found 1 slot(s) of which 0 tokenless/unsupported
debug: ykcs11.c:109 (C_Initialize): Out
Returned:  0 CKR_OK

2: C_GetInfo
2016-10-01 23:07:46.961
debug: ykcs11.c:149 (C_GetInfo): In
debug: ykcs11.c:163 (C_GetInfo): Out
[out] pInfo: 
      cryptokiVersion:         2.40
      manufacturerID:         '         Yubico (www.yubico.com)'
      flags:                   0
      libraryDescription:     ' PKCS#11 PIV Library (SP-800-73)'
      libraryVersion:          1.42
Returned:  0 CKR_OK

3: C_GetSlotList
2016-10-01 23:07:46.961
[in] tokenPresent = 0x1
debug: ykcs11.c:194 (C_GetSlotList): In
debug: ykcs11.c:231 (C_GetSlotList): token present is 1
debug: ykcs11.c:232 (C_GetSlotList): number of slot(s) is 1
debug: ykcs11.c:234 (C_GetSlotList): Out
[out] pSlotList: 
Slot 0
[out] *pulCount = 0x1
Returned:  0 CKR_OK

4: C_GetTokenInfo
2016-10-01 23:07:46.961
[in] slotID = 0x0
debug: ykcs11.c:266 (C_GetTokenInfo): In
debug: ykcs11.c:307 (C_GetTokenInfo): Out
[out] pInfo: 
      label:                  'YubiKey PIV                     '
      manufacturerID:         'Yubico                          '
      model:                  'YubiKey NEO     '
      serialNumber:           '1234            '
      ulMaxSessionCount:       -1
      ulSessionCount:          -1
      ulMaxRwSessionCount:     -1
      ulRwSessionCount:        -1
      ulMaxPinLen:             8
      ulMinPinLen:             6
      ulTotalPublicMemory:     -1
      ulFreePublicMemory:      -1
      ulTotalPrivateMemory:    -1
      ulFreePrivateMemory:     -1
      hardwareVersion:         112.116
      firmwareVersion:         0.101
      time:                   '                '
      flags:                   40d
        CKF_RNG                          
        CKF_LOGIN_REQUIRED               
        CKF_USER_PIN_INITIALIZED         
        CKF_TOKEN_INITIALIZED            
Returned:  0 CKR_OK

5: C_GetSlotInfo
2016-10-01 23:07:46.961
[in] slotID = 0x0
debug: ykcs11.c:243 (C_GetSlotInfo): In
debug: ykcs11.c:257 (C_GetSlotInfo): Out
[out] pInfo: 
      slotDescription:        'Yubico Yubikey NEO OTP+CCID 00 0'
                              '                               0'
      manufacturerID:         'Yubico                          '
      hardwareVersion:         1.0
      firmwareVersion:         1.0
      flags:                   5
        CKF_TOKEN_PRESENT                
        CKF_HW_SLOT                      
Returned:  0 CKR_OK

6: C_OpenSession
2016-10-01 23:07:46.961
[in] slotID = 0x0
[in] flags = 0x4
pApplication=(nil)
Notify=(nil)
debug: ykcs11.c:506 (C_OpenSession): In
trying to connect to reader 'Yubico Yubikey NEO OTP+CCID 00 00'.
debug: yubico_token.c:273 (get_objects): Found AUTH cert (9a)
debug: yubico_token.c:282 (get_objects): Found CARD AUTH cert (9e)
debug: yubico_token.c:291 (get_objects): Found SIGNATURE cert (9c)
debug: yubico_token.c:300 (get_objects): Found KMK cert (9d)
debug: yubico_token.c:317 (get_objects): The total number of objects for this token is 21
debug: yubico_token.c:273 (get_objects): Found AUTH cert (9a)
debug: yubico_token.c:282 (get_objects): Found CARD AUTH cert (9e)
debug: yubico_token.c:291 (get_objects): Found SIGNATURE cert (9c)
debug: yubico_token.c:300 (get_objects): Found KMK cert (9d)
debug: yubico_token.c:317 (get_objects): The total number of objects for this token is 21
debug: ykcs11.c:622 (C_OpenSession): Unable to store certificate data
[out] *phSession = 0x0
Returned:  6 CKR_FUNCTION_FAILED

7: C_Finalize
2016-10-01 23:07:48.624
debug: ykcs11.c:119 (C_Finalize): In
debug: ykcs11.c:139 (C_Finalize): Out
Returned:  0 CKR_OK

@dwmw2
Copy link
Author

dwmw2 commented Oct 1, 2016

I guess this is probably a combination of lack of support for gzip'd certificates (see commit 3dce5b0) and poor error reporting from do_store_cert() when it can't read the cert.

@dwmw2
Copy link
Author

dwmw2 commented Oct 1, 2016

It's d2i_X509() which is failing. Which is hardly surprising really, when you feed it something that looks like this...

0000: 0x70 0x82 0x05 0x84 0x1f 0x8b 0x08 0x00 0x41 0xd9 0x5c 0x54 0x02 0x03 0x33 0x68 
0010: 0xe2 0x28 0x36 0x68 0x62 0x8f 0x5e 0xc0 0xcc 0xc4 0xc8 0xc4 0xc4 0x25 0xb7 0xe9 
...

@dwmw2 dwmw2 changed the title C_OpenSession fails C_OpenSession fails with compressed certificates on device Oct 1, 2016
@dwmw2
Copy link
Author

dwmw2 commented Oct 1, 2016

Proof of concept gets me to the next step...

--- a/ykcs11/openssl_utils.c
+++ b/ykcs11/openssl_utils.c
@@ -33,16 +33,43 @@
 #include "../tool/util.h" // TODO: share this better?
 #include "debug.h"
 #include <string.h>
+#include <zlib.h>

 CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) {

   const unsigned char *p = data; // Mandatory temp variable required by OpenSSL
   int                 cert_len;
+  unsigned char buf[8192];

   if (*p == 0x70) {
     // The certificate is in "PIV" format 0x70 len 0x30 len ...
     p++;
     p += get_length(p, &cert_len);
+    /* We should check the 0x71 tag not do this hack */
+    if (*p == 0x1f) {
+       z_stream str;
+
+       memset(&str, 0, sizeof(str));
+       str.next_in = p;
+       str.avail_in = cert_len;
+       str.next_out = buf;
+       str.avail_out = sizeof(buf);
+       if (inflateInit2(&str, 15 + 0x20) != Z_OK) {
+           printf("no init\n");
+           return CKR_FUNCTION_FAILED;
+       }
+       if (inflate(&str, Z_FINISH) != Z_STREAM_END) {
+           printf("no inflate\n");
+           inflateEnd(&str);
+           return CKR_FUNCTION_FAILED;
+       }
+       cert_len = str.total_out;
+       p = buf;
+
+       inflateEnd(&str);
+
+       goto d2i;
+    }
   }
   else {
     // Raw certificate 0x30 len ...
@@ -50,12 +77,16 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) {
     cert_len += get_length(p + 1, &cert_len) + 1;
   }

-  if ((CK_ULONG)cert_len > len)
+  if ((CK_ULONG)cert_len > len) {
+     printf("bad %lx %lx\n", cert_len, len);
     return CKR_ARGUMENTS_BAD;
-
+  }
+  d2i:
   *cert = d2i_X509(NULL, &p, cert_len);
-  if (*cert == NULL)
+  if (*cert == NULL) {
+     printf("d2i failed\n");
     return CKR_FUNCTION_FAILED;
+  }

   return CKR_OK;


@dwmw2
Copy link
Author

dwmw2 commented Oct 1, 2016

... and this finally makes it work for my first real test case

--- a/ykcs11/objects.c
+++ b/ykcs11/objects.c
@@ -476,7 +476,7 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
 /* Get certificate object attribute */
 CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
   CK_BYTE_PTR data;
-  CK_BYTE     b_tmp[1024];
+  CK_BYTE     b_tmp[8192];
   CK_ULONG    ul_tmp;
   CK_ULONG    len = 0;
   DBG("For certificate object %lu, get ", obj);

@dwmw2
Copy link
Author

dwmw2 commented Oct 3, 2016

Quoting from #94 (comment):

For example regarding #93 linking against zlib is fine, but I think that that part should be moved from the module into libykpiv.

Note that in the above proof-of-concept hack, I said nothing about linking to zlib; I just started using it. I think it ended up being transitively linked or something like that, and we'd probably want to fix that :)

We also want to support zlib-compressed objects (we can just use uncompress for that).

We have been discussing internally about adding a series of utility functions ykpiv_util_* to libykpiv so that we could address high level operations like load a certificate, load a private key, generate a selfsigned certificate, etc. This would simplify the logic both in yubico-piv-tool and in ykcs11. However, as you can imagine it requires some time and work.

Yeah. When I added support for writing compressed objects, I did say we should make it use zlib and compress them for itself. We'd want to do that too. And while we're at it, we should make the import functionality for both keys and certificate files conform to http://david.woodhou.se/draft-woodhouse-cert-best-practice.html ... but yes, time and work.

@qpernil
Copy link
Contributor

qpernil commented Feb 18, 2020

I've had a look at this an it's a candidate for the next minor release after 2.0.0

@qpernil
Copy link
Contributor

qpernil commented Dec 27, 2023

#437 should address this issue.

@qpernil
Copy link
Contributor

qpernil commented Dec 27, 2023

Closing this issue now, please open a new issues as needed.

@qpernil qpernil closed this as completed Dec 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants