Code Monkey home page Code Monkey logo

kryoptic's Introduction

This is a pkcs11 soft token written in rust

Dependencies

  • rustc
  • openssl dependencies
  • sqlite

Setup

First after cloning, we need to pull and update openssl submodule:

$ git submodule init
$ git submodule update

Build the rust project:

$ cargo build

For FIPS module, you need to generate hmac checksum:

$ ./hmacify.sh target/release/libkryoptic_pkcs11.so

Tests

To run test, run the check command:

$ cargo test

kryoptic's People

Contributors

simo5 avatar jakuje avatar sarroutbi avatar

Stargazers

Nicola Tuveri avatar Hatter Jiang avatar Faisal Chaudhry avatar LIN,SHANG-CHING avatar Alexander Sosedkin avatar  avatar  avatar  avatar

Watchers

Nicola Tuveri avatar  avatar  avatar  avatar  avatar

kryoptic's Issues

Support for CKA_ALWAYS_AUTHENTICATE

The CKA_ALWAYS_AUTHENTICATE should enforce the private key is used only immediately after providing the user consent (PIN).

The attribute can be provided as any other object during writing or generating private key and should be visible for the user.

This login state should be tracked as part of the session, which carries already information if the session is in logged in state. This needs to set specific flag the Login was called and it needs to be reset when different function will be called.

Implement a vendor KDF for SSH-KDF

SSH-KDF is similar to SP800 KDF and PBKDF2 in some ways, but it uses just a hash instead of a proper HMAC and no counter, instead re-hashes in the previous hash when expansion is needed.

This means none of the standard PKCS#11 KDFs really cover it and will need to elaborate a new proposal, starting with implementing a vendor namespaced version to kick the tires.

Create a sqlite storage inspector or dbdump to allow inspection of DB

At some points it might be helpful to be able to see the private properties of stored object that are not visible through the standard PKCS#11 interface.

Reading of the JSON files is cumbersome, but reading the sqlite format is much less user friendly now. It might be also used as a backup/restore tool later on, but it should not grow over to something like certtool, I think.

Make sqlite storage file format platform neutral

CK_ULONG type attributes are stored as byte sequences, this makes them incompatible with reading the db on platform with different endianess or unsigned long size.

For maximum compatibility we should turn CK_ULONG values to a specific endian u32 value, before storage. (the PKCS#11 doesn't say it very explicitly but CK_ULONG values are supposed to be u32 compatible).

NULL values should also be supported, currently the code fails to read and convert a NULL value to something sensible, but some attributes may need to store a 0 length vector, to indicate the attribute is present, just intentionally empty.

Implement CKM_RSA_AES_KEY_WRAP

Requires some thinking about using one operation from another operation (nesting).
Also requires implementing CKM_AES_KEY_WRAP_KWP

Test interoperability of asymmetric key wrapping and unwrapping

The asymmetric key (RSA, ECDSA) wrapping and unwrapping works on kryoptic, but it involves a lot of ASN.1 encoding and decoding so it would be useful to test interoperability of these operations on some other implementation to make sure we do the right thing.

store CKA_VALUE_LEN on all key objects

For asymmetric key types the size of the keys is obvious and encoded (one way or another) in public parameters.
However for symmetric keys, the only way to know the key length is to expose the CKA_VALUE_LEN parameter, because CKA_VALUE is never returned.
Ensure we always store CKA_VALUE_LEN (derived from CKA_VALUE or retained during generation/unwrap) on secret objects.

Consider reviewing all uses of "as" conversions

The "as" conversion truncates values when the receiving type is smaller leading to difficult to reason edge cases. We should review all uses of "as" to asses where try_from() is more appropriate.

token does not export PIN related flags

These flags are defined for USER and SO PINs:
#define CKF_USER_PIN_COUNT_LOW 0x00010000UL
#define CKF_USER_PIN_FINAL_TRY 0x00020000UL
#define CKF_USER_PIN_LOCKED 0x00040000UL
#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000UL
#define CKF_SO_PIN_COUNT_LOW 0x00100000UL
#define CKF_SO_PIN_FINAL_TRY 0x00200000UL
#define CKF_SO_PIN_LOCKED 0x00400000UL
#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000UL

But we do not expose them when these events occur.

Support default storage location

          Should we add a default place to look at when no env var is set ?

(perhaps in a separate PR)

Originally posted by @simo5 in #35 (comment)

This was discussed previously and we considered some defaults like:

  • if root: some system wide location
  • else: try XDG_CONFIG_HOME [1] or something like that

The environment variable and pReserved argument to Initialize should override the defaults.

[1] https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html

The PIN objects should not be propagated to the PKCS#11 interface

For PIN objects, we should we either:

  • use some vendor specific types to avoid applications interpreting these as they are propagated to pkcs11 layer
  • filter the PIN objects from the pkcs11-layer results?

(or both)

Right now, it is possible to find the PIN objects through searching for the SECRET keys:

5489: C_FindObjectsInit
P:2440186; T:0x140007141424576 2024-03-25 15:09:17.251
[in] hSession = 0x11
[in] pTemplate[1]: 
    CKA_CLASS             CKO_SECRET_KEY       
Returned:  0 CKR_OK

5490: C_FindObjects
P:2440186; T:0x140007141424576 2024-03-25 15:09:17.251
[in] hSession = 0x11
[in] ulMaxObjectCount = 0x1
[out] ulObjectCount = 0x1
Object 0x9 matches
Returned:  0 CKR_OK

314: C_GetAttributeValue
P:2440186; T:0x140007141424576 2024-03-25 15:09:15.882
[in] hSession = 0x11
[in] hObject = 0xc
[in] pTemplate[1]: 
    CKA_LABEL             000000000073c010 / 8
[out] pTemplate[1]: 
    CKA_LABEL             000000000073c010 / 8
    55736572 2050494E
     U s e r  . P I N
Returned:  0 CKR_OK

The objects do not have CKA_ID so most of the application will likely to ignore them but we should not depend on that and not show them to user/application.

Originally posted by @Jakuje in #17 (comment)

Unwrapped AES keys do not work

The unwrapped AES keys have empty CKA_VALUE, which can be reproduced with the following test (it fails while importing the key as the CKA_VALUE in storage is empty):

Jakuje@23d2a43

I was not completely sure how to fix it as I am slightly lost in the attributes flags. There is OAFlags::UnsettableOnUnwrap, which is used only on the secret keys CKA_VALUE, according to the name it makes sense, but the function that is checking this flag now operates only on template (instead of on the created attrs vec) here:

let result = self.default_object_unwrap(template);

I think this should operate on &atrs but then we need to change the flags for CKA_VALUE so it can be set from this function (now it would fail).

Consider tweaking the ffi bindings to add lifetimes

Many PKCS#11 structures carry "naked" pointers to other structures or buffers.

On the caller side there we can only hope the application calling in does the right thing, however when we call ourselves internally (in tests or when implementing complex chained functions) having lifetimes will allow the compiler to ensure we keep data around for the time necessary.

This is particularly useful for structures like CK_ATTRIBUTE which are useful to manipulate in helper functions, but require very careful management of the pointers to ensure the data is not some pointer allocated on the stack after we return from the helper.

Similarly actually for OSSL_PARAM when we call into openssl and want to use a hlper to fill in an array of params.

Review helper construct's lifetime promises

In some helper structures in ossl/common.c we play with pointers of contexts and other structures, we need to review if lifetimes need to be explicitly used, to avoid cases where Rust may think it is safe to drop some memory while openssl embedded a pointer to the same memory in some internal context, like with pkey structures.

Use generic PrivateKeyInfo

Currently, there is separate copy of PrivateKeyInfo in RSA and ECC code, handling the wrapping and unwrapping of private keys.

Simo suggested that this would be something that could be used with #defined_by(OID) of rust-asn1 library to provide generic structure. The WIP branch implementing this is available here (but still has some memory ownership issues to resolve):

https://github.com/Jakuje/kryoptic/commits/defined-by/

          sounds like this is a place where to use:

#[defined_by(private_key_algorithm)]

See: https://docs.rs/asn1/latest/asn1/#defined-by

Originally posted by @simo5 in #5 (comment)

ECDH should accept DER encoded EC point

ECDH test in pkcs11-provider (which just started testing with kryoptic) shows ECDH failing.

After some investigation this is due to pkcs11-provider passing in a DER encoded point in pPublicData instead of a raw point (I beleive this was because softhsm only accepted this format at some point).

The spec says:

pPublicData       pointer to other party’s EC public key value. For short Weierstrass
                  EC keys: a token MUST be able to accept this value encoded as a raw
                  octet string (as per section A.5.2 of [ANSI X9.62]).  A token MAY, 
                  in addition, support accepting this value as a DER-encoded ECPoint 
                  (as per section E.6 of [ANSI X9.62]) i.e. the same as a CKA_EC_POINT
                  encoding.  The calling application is responsible for converting the
                  offered public key to the compressed or uncompressed forms of these
                  encodings if the token does not support the offered form.

So technically we could ignore and fault on DER encoded points, but we should detect and
convert the point like NSS softoken does, because it is easy to do so.

Implement the remaining PKCS 3.0 functions, namely message based operations

The 3.0 defines message-based encryption/decryption/signature/verification, where at least the encryption and decryption might be useful.

Then there are dual-function operations, such as C_SignEncryptUpdate(), which might be relevant for FIPS as it does both signature+encryption at one step. I do not think we have a good use for these now, but it should be easy to combine them from existing operations.

Support for private keys that do not need login

In most of the reasonable cases (and as implemented now), the login is required to do private key operations on a token. But there is at least a PIV token (at least as implemented in yubikey), which has a certificate slot 9e not requiring the login for the operations:

https://developers.yubico.com/PIV/Introduction/Certificate_slots.html

I am not sure if there is a good way to represent this on the PKCS#11 level though.

          AFAIK this could be also configured by token, but I can not find the PKCS#11 object, that controls this though (not sure if there is one even standardized). But there are yubikeys (and some PIV cards) having a private key slot 9e, that can be used without login, causing various issues: https://developers.yubico.com/PIV/Introduction/Certificate_slots.html Not sure if it makes sense to consider it here, but again maybe worth TODO comment too.

Originally posted by @Jakuje in #17 (comment)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.