URIs

## URIs URIs — Parsing and formatting PKCS#11 URIs |

## Synopsis

    #define             P11_KIT_URI_SCHEME
    #define             P11_KIT_URI_SCHEME_LEN
    enum                P11KitUriType;
    enum                P11KitUriResult;
    typedef             P11KitUri;
    typedef             p11_kit_uri;
    P11KitUri *         p11_kit_uri_new                     (void);
    CK_INFO_PTR         p11_kit_uri_get_module_info         (P11KitUri *uri);
    int                 p11_kit_uri_match_module_info       (P11KitUri *uri,
                                                             CK_INFO_PTR info);
    CK_TOKEN_INFO_PTR   p11_kit_uri_get_token_info          (P11KitUri *uri);
    int                 p11_kit_uri_match_token_info        (P11KitUri *uri,
                                                             CK_TOKEN_INFO_PTR token_info);
    CK_ATTRIBUTE_PTR    p11_kit_uri_get_attributes          (P11KitUri *uri,
                                                             CK_ULONG *n_attrs);
    int                 p11_kit_uri_set_attributes          (P11KitUri *uri,
                                                             CK_ATTRIBUTE_PTR attrs,
                                                             CK_ULONG n_attrs);
    void                p11_kit_uri_clear_attributes        (P11KitUri *uri);
    int                 p11_kit_uri_match_attributes        (P11KitUri *uri,
                                                             CK_ATTRIBUTE_PTR attrs,
                                                             CK_ULONG n_attrs);
    CK_ATTRIBUTE_PTR    p11_kit_uri_get_attribute           (P11KitUri *uri,
                                                             CK_ATTRIBUTE_TYPE attr_type);
    int                 p11_kit_uri_set_attribute           (P11KitUri *uri,
                                                             CK_ATTRIBUTE_PTR attr);
    int                 p11_kit_uri_clear_attribute         (P11KitUri *uri,
                                                             CK_ATTRIBUTE_TYPE attr_type);
    void                p11_kit_uri_set_unrecognized        (P11KitUri *uri,
                                                             int unrecognized);
    int                 p11_kit_uri_any_unrecognized        (P11KitUri *uri);
    const char *        p11_kit_uri_get_pin_source          (P11KitUri *uri);
    void                p11_kit_uri_set_pin_source          (P11KitUri *uri,
                                                             const char *pin_source);
    const char *        p11_kit_uri_get_pinfile             (P11KitUri *uri);
    void                p11_kit_uri_set_pinfile             (P11KitUri *uri,
                                                             const char *pinfile);
    int                 p11_kit_uri_format                  (P11KitUri *uri,
                                                             P11KitUriType uri_type,
                                                             char **string);
    int                 p11_kit_uri_parse                   (const char *string,
                                                             P11KitUriType uri_type,
                                                             P11KitUri *uri);
    void                p11_kit_uri_free                    (P11KitUri *uri);
    const char *        p11_kit_uri_message                 (int code);
    #define             P11_KIT_URI_NO_MEMORY

## Description

PKCS#11 URIs can be used in configuration files or applications to represent PKCS#11 modules, tokens or objects. An example of a URI might be:

``

pkcs11:token=The%20Software%20PKCS#11%20softtoken;
manufacturer=Snake%20Oil,%20Inc.;serial=;object=my-certificate;
model=1.0;object-type=cert;id=%69%95%3e%5c%f4%bd%ec%91

You can use `p11_kit_uri_parse()` to parse such a URI, and `p11_kit_uri_format()` to build one. URIs are represented by the P11KitUri structure. You can match a parsed URI against PKCS#11 tokens with `p11_kit_uri_match_token_info()` or attributes with `p11_kit_uri_match_attributes()`.

Since URIs can represent different sorts of things, when parsing or formatting a URI a 'context' can be used to indicate which sort of URI is expected.

URIs have an `unrecognized` flag. This flag is set during parsing if any parts of the URI are not recognized. This may be because the part is from a newer version of the PKCS#11 spec or because that part was not valid inside of the desired context used when parsing.

## Details

### P11_KIT_URI_SCHEME

    #define P11_KIT_URI_SCHEME "pkcs11"

String of URI scheme for PKCS#11 URIs.

### P11_KIT_URI_SCHEME_LEN

    #define P11_KIT_URI_SCHEME_LEN 6

Length of `P11_KIT_URI_SCHEME`.

### enum P11KitUriType

    typedef enum {
    	P11_KIT_URI_FOR_OBJECT =  (1 << 1),
    	P11_KIT_URI_FOR_TOKEN =   (1 << 2),
    	P11_KIT_URI_FOR_MODULE =  (1 << 3),

    	P11_KIT_URI_FOR_MODULE_WITH_VERSION =
    		(1 << 4) | P11_KIT_URI_FOR_MODULE,

    	P11_KIT_URI_FOR_OBJECT_ON_TOKEN =
    		P11_KIT_URI_FOR_OBJECT | P11_KIT_URI_FOR_TOKEN,

    	P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE =
    		P11_KIT_URI_FOR_OBJECT_ON_TOKEN | P11_KIT_URI_FOR_MODULE,

    	P11_KIT_URI_FOR_ANY =     0x0000FFFF,
    } P11KitUriType;

A PKCS#11 URI can represent different kinds of things. This flag is used by `p11_kit_uri_parse()` to denote in what context the URI will be used.

The various types can be combined.

`P11_KIT_URI_FOR_OBJECT` | The URI represents one or more objects
`P11_KIT_URI_FOR_TOKEN` | The URI represents one or more tokens
`P11_KIT_URI_FOR_MODULE` | The URI represents one or more modules
`P11_KIT_URI_FOR_MODULE_WITH_VERSION` | The URI represents a module with a specific version.
`P11_KIT_URI_FOR_OBJECT_ON_TOKEN` | The URI represents one or more objects that are present on a specific token.
`P11_KIT_URI_FOR_OBJECT_ON_TOKEN_AND_MODULE` | The URI represents one or more objects that are present on a specific token, being used with a certain module.
`P11_KIT_URI_FOR_ANY` | The URI can represent anything

### enum P11KitUriResult

    typedef enum {
    	P11_KIT_URI_OK = 0,
    	P11_KIT_URI_UNEXPECTED = -1,
    	P11_KIT_URI_BAD_SCHEME = -2,
    	P11_KIT_URI_BAD_ENCODING = -3,
    	P11_KIT_URI_BAD_SYNTAX = -4,
    	P11_KIT_URI_BAD_VERSION = -5,
    	P11_KIT_URI_NOT_FOUND = -6,
    } P11KitUriResult;

Error codes returned by various functions. The functions each clearly state which error codes they are capable of returning.

`P11_KIT_URI_OK` | Success
`P11_KIT_URI_UNEXPECTED` | Unexpected or internal system error
`P11_KIT_URI_BAD_SCHEME` | The URI had a bad scheme
`P11_KIT_URI_BAD_ENCODING` | The URI had a bad encoding
`P11_KIT_URI_BAD_SYNTAX` | The URI had a bad syntax
`P11_KIT_URI_BAD_VERSION` | The URI contained a bad version number
`P11_KIT_URI_NOT_FOUND` | A requested part of the URI was not found

### P11KitUri

    typedef struct p11_kit_uri P11KitUri;

A structure representing a PKCS#11 URI. There are no public fields visible in this structure. Use the various accessor functions.

### p11_kit_uri

    typedef struct p11_kit_uri p11_kit_uri;

### p11_kit_uri_new ()

    P11KitUri *         p11_kit_uri_new                     (void);

Create a new blank PKCS#11 URI.

The new URI is in the right state to parse a string into. All relevant fields are zeroed out. Formatting this URI will produce a valid but empty URI.

Returns : | A newly allocated URI. This should be freed with `p11_kit_uri_free()`.

### p11_kit_uri_get_module_info ()

    CK_INFO_PTR         p11_kit_uri_get_module_info         (P11KitUri *uri);

Get the `CK_INFO` structure associated with this URI.

If this is a parsed URI, then the fields corresponding to library parts of the URI will be filled in. Any library URI parts that were missing will have their fields filled with zeros.

If the caller wishes to setup information for building a URI, then relevant fields should be filled in. Fields that should not appear as parts in the resulting URI should be filled with zeros.

`uri` : | the URI
Returns : | A pointer to the `CK_INFO` structure.

### p11_kit_uri_match_module_info ()

    int                 p11_kit_uri_match_module_info       (P11KitUri *uri,
                                                             CK_INFO_PTR info);

Match a `CK_INFO` structure against the library parts of this URI.

Only the fields of the `CK_INFO` structure that are valid for use in a URI will be matched. A URI part that was not specified in the URI will match any value in the structure. If during the URI parsing any unrecognized parts were encountered then this match will fail.

`uri` : | the URI
`info` : | the structure to match against the URI
Returns : | 1 if the URI matches, 0 if not.

### p11_kit_uri_get_token_info ()

    CK_TOKEN_INFO_PTR   p11_kit_uri_get_token_info          (P11KitUri *uri);

Get the `CK_TOKEN_INFO` structure associated with this URI.

If this is a parsed URI, then the fields corresponding to token parts of the URI will be filled in. Any token URI parts that were missing will have their fields filled with zeros.

If the caller wishes to setup information for building a URI, then relevant fields should be filled in. Fields that should not appear as parts in the resulting URI should be filled with zeros.

`uri` : | the URI
Returns : | A pointer to the `CK_INFO` structure.

### p11_kit_uri_match_token_info ()

    int                 p11_kit_uri_match_token_info        (P11KitUri *uri,
                                                             CK_TOKEN_INFO_PTR token_info);

Match a `CK_TOKEN_INFO` structure against the token parts of this URI.

Only the fields of the `CK_TOKEN_INFO` structure that are valid for use in a URI will be matched. A URI part that was not specified in the URI will match any value in the structure. If during the URI parsing any unrecognized parts were encountered then this match will fail.

`uri` : | the URI
`token_info` : | the structure to match against the URI
Returns : | 1 if the URI matches, 0 if not.

### p11_kit_uri_get_attributes ()

    CK_ATTRIBUTE_PTR    p11_kit_uri_get_attributes          (P11KitUri *uri,
                                                             CK_ULONG *n_attrs);

### p11_kit_uri_set_attributes ()

    int                 p11_kit_uri_set_attributes          (P11KitUri *uri,
                                                             CK_ATTRIBUTE_PTR attrs,
                                                             CK_ULONG n_attrs);

### p11_kit_uri_clear_attributes ()

    void                p11_kit_uri_clear_attributes        (P11KitUri *uri);

### p11_kit_uri_match_attributes ()

    int                 p11_kit_uri_match_attributes        (P11KitUri *uri,
                                                             CK_ATTRIBUTE_PTR attrs,
                                                             CK_ULONG n_attrs);

Match a attributes against the object parts of this URI.

Only the attributes that are valid for use in a URI will be matched. A URI part that was not specified in the URI will match any attribute value. If during the URI parsing any unrecognized parts were encountered then this match will fail.

`uri` : | The URI
`attrs` : | The attributes to match
`n_attrs` : | The number of attributes
Returns : | 1 if the URI matches, 0 if not.

### p11_kit_uri_get_attribute ()

    CK_ATTRIBUTE_PTR    p11_kit_uri_get_attribute           (P11KitUri *uri,
                                                             CK_ATTRIBUTE_TYPE attr_type);

Get a pointer to an attribute present in this URI.

`uri` : | The URI
`attr_type` : | The attribute type
Returns : | A pointer to the attribute, or `NULL` if not present. The attribute is owned by the URI and should not be freed.

### p11_kit_uri_set_attribute ()

    int                 p11_kit_uri_set_attribute           (P11KitUri *uri,
                                                             CK_ATTRIBUTE_PTR attr);

Set an attribute on the URI.

Only attributes that map to parts in a PKCS#11 URI will be accepted.

`uri` : | The URI
`attr` : | The attribute to set
Returns : | `P11_KIT_URI_OK` if the attribute was successfully set. `P11_KIT_URI_NOT_FOUND` if the attribute was not valid for a URI.

### p11_kit_uri_clear_attribute ()

    int                 p11_kit_uri_clear_attribute         (P11KitUri *uri,
                                                             CK_ATTRIBUTE_TYPE attr_type);

Clear an attribute on the URI.

Only attributes that map to parts in a PKCS#11 URI will be accepted.

`uri` : | The URI
`attr_type` : | The type of the attribute to clear
Returns : | `P11_KIT_URI_OK` if the attribute was successfully cleared. `P11_KIT_URI_NOT_FOUND` if the attribute was not valid for a URI.

### p11_kit_uri_set_unrecognized ()

    void                p11_kit_uri_set_unrecognized        (P11KitUri *uri,
                                                             int unrecognized);

Set the unrecognized flag on this URI.

The unrecognized flag is automatically set to 1 when during parsing any part of the URI is unrecognized. If the unrecognized flag is set to 1, then matching against this URI will always fail.

`uri` : | The URI
`unrecognized` : | The new unregognized flag value

### p11_kit_uri_any_unrecognized ()

    int                 p11_kit_uri_any_unrecognized        (P11KitUri *uri);

Get the unrecognized flag for this URI.

The unrecognized flag is automatically set to 1 when during parsing any part of the URI is unrecognized. If the unrecognized flag is set to 1, then matching against this URI will always fail.

`uri` : | The URI
Returns : | 1 if unrecognized flag is set, 0 otherwise.

### p11_kit_uri_get_pin_source ()

    const char *        p11_kit_uri_get_pin_source          (P11KitUri *uri);

Get the 'pin-source' part of the URI. This is used by some applications to lookup a PIN for logging into a PKCS#11 token.

`uri` : | The URI
Returns : | The pin-source or `NULL` if not present.

### p11_kit_uri_set_pin_source ()

    void                p11_kit_uri_set_pin_source          (P11KitUri *uri,
                                                             const char *pin_source);

Set the 'pin-source' part of the URI. This is used by some applications to lookup a PIN for logging into a PKCS#11 token.

`uri` : | The URI
`pin_source` : | The new pin-source

### p11_kit_uri_get_pinfile ()

    const char *        p11_kit_uri_get_pinfile             (P11KitUri *uri);

### Warning

`p11_kit_uri_get_pinfile` is deprecated and should not be used in newly-written code. use `p11_kit_uri_get_pin_source()`.

`uri` : | The URI

### p11_kit_uri_set_pinfile ()

    void                p11_kit_uri_set_pinfile             (P11KitUri *uri,
                                                             const char *pinfile);

### Warning

`p11_kit_uri_set_pinfile` is deprecated and should not be used in newly-written code. use `p11_kit_uri_set_pin_source()`.

`uri` : | The URI
`pinfile` : | The pinfile

### p11_kit_uri_format ()

    int                 p11_kit_uri_format                  (P11KitUri *uri,
                                                             P11KitUriType uri_type,
                                                             char **string);

Format a PKCS#11 URI into a string.

Fields which are zeroed out will not be included in the resulting string. Attributes which are not present will also not be included.

The uri_type of URI specified limits the different parts of the resulting URI. To format a URI containing all possible information use `P11_KIT_URI_FOR_ANY`

It's up to the caller to guarantee that the attributes set in `uri` are those appropriate for inclusion in a URI, specifically: `CKA_ID`, `CKA_LABEL` and `CKA_CLASS`. The class must be one of `CKO_DATA`, `CKO_SECRET_KEY`, `CKO_CERTIFICATE`, `CKO_PUBLIC_KEY`, `CKO_PRIVATE_KEY`.

The resulting string should be freed with `free()`.

`uri` : | The URI.
`uri_type` : | The type of URI that should be produced.
`string` : | Location to store a newly allocated string.
Returns : | `P11_KIT_URI_OK` if the URI was formatted successfully, `P11_KIT_URI_UNEXPECTED` if the data in `uri` is invalid for a URI.

### p11_kit_uri_parse ()

    int                 p11_kit_uri_parse                   (const char *string,
                                                             P11KitUriType uri_type,
                                                             P11KitUri *uri);

Parse a PKCS#11 URI string.

PKCS#11 URIs can represent tokens, objects or modules. The uri_type argument allows the caller to specify what type of URI is expected and the sorts of things the URI should match. `P11_KIT_URI_FOR_ANY` can be used to parse a URI for any context. It's then up to the caller to make sense of the way that it is used.

If the PKCS#11 URI contains unrecognized URI parts or parts not applicable to the specified context, then the unrecognized flag will be set. This will prevent the URI from matching using the various match functions.

`string` : | The string to parse
`uri_type` : | The type of URI that is expected
`uri` : | The blank URI to parse the values into
Returns : | `P11_KIT_URI_OK` if the URI was parsed successfully. `P11_KIT_URI_BAD_SCHEME` if this was not a PKCS#11 URI. `P11_KIT_URI_BAD_SYNTAX` if the URI syntax was bad. `P11_KIT_URI_BAD_VERSION` if a version number was bad. `P11_KIT_URI_BAD_ENCODING` if the URI encoding was invalid.

### p11_kit_uri_free ()

    void                p11_kit_uri_free                    (P11KitUri *uri);

Free a PKCS#11 URI.

`uri` : | The URI

### p11_kit_uri_message ()

    const char *        p11_kit_uri_message                 (int code);

Lookup a message for the uri error code. These codes are the P11_KIT_URI_XXX error codes that can be returned from `p11_kit_uri_parse()` or `p11_kit_uri_format()`. As a special case `NULL`, will be returned for `P11_KIT_URI_OK`.

`code` : | The error code
Returns : | The message for the error code. This string is owned by the p11-kit library.

### P11_KIT_URI_NO_MEMORY

    #define P11_KIT_URI_NO_MEMORY P11_KIT_URI_UNEXPECTED

Unexpected memory allocation failure result. Same as P11_KIT_URI_UNEXPECTED.