# Certificates

Certificates are represented by the `ec_cert_t` type, and are created by `ec_cert_create()`. All certificates must be freed once they are no longer required using `ec_cert_destroy()`.

If a certificate has been saved using `ec_ctx_save()`, then it will be destroyed automatically once it is removed, overwritten, or the context it was saved to is destroyed.

## API

* [ec\_cert\_create()](#ec-cert-create)
* [ec\_cert\_copy()](#ec-cert-copy)
* [ec\_cert\_destroy()](#ec-cert-destroy)
* [ec\_cert\_strip()](#ec-cert-strip)
* [ec\_cert\_sign()](#ec-cert-sign)
* [ec\_cert\_check()](#ec-cert-check)
* [ec\_cert\_id()](#ec-cert-id)
* [ec\_cert\_records()](#ec-cert-records)
* [ec\_cert\_lock()](#ec-cert-lock)
* [ec\_cert\_unlock()](#ec-cert-unlock)

### ec\_cert\_create()

`ec_cert_t *ec_cert_create(time_t valid_from, time_t valid_until);`

Create a new certificate, and return a pointer to it. Returns NULL on failure. `valid_from` and `valid_until` define the certificate's validity period - if the validity period does not fall entirely within the valitity period of its signer, then the timestamp which violates this constraint will be adjusted to match that of the signer.

Timestamps are handled as seconds since 1970-01-01 00:00:00. The current time can be obtained using `time()` (see `time.h`).

Certificates created using this function must be destroyed using `ec_cert_destroy()` when they are no longer required.

```c
#include <ec.h>
#include <time.h>
...
time_t from = time(NULL);
time_t until = from + (86400 * 365); //one year
ec_cert_t *c = ec_cert_create(from, until);
...
```

### ec\_cert\_copy()

`ec_cert_t *ec_cert_copy(ec_cert_t *c);`

Copy a certificate. Returns a new copy of `c`, or NULL on failure.

```c
#include <ec.h>
...
ec_cert_t *c2 = ec_cert_copy(c1);
if(c == NULL) {
    //failed to copy certificate
}
...
```

### ec\_cert\_destroy()

`void ec_cert_destroy(ec_cert_t *c);`

Destroy a certificate previously created with `ec_cert_create()`.

```c
#include <ec.h>
...
ec_cert_destroy(c);
...
```

### ec\_cert\_strip()

`void ec_cert_strip(ec_cert_t *c, int what);`

Strip unwanted data from a certificate, specified by `when`. Possible flags are listed below:

| Flag              | Removed Data                            |
| ----------------- | --------------------------------------- |
| EC\_STRIP\_SECRET | Secret key                              |
| EC\_STRIP\_RECORD | All records with EC\_RECORD\_NOSIGN set |
| EC\_STRIP\_SIGN   | Signer ID & signature                   |

```c
#include <ec.h>
...
ec_cert_strip(c, EC_STRIP_SECRET | EC_STRIP_RECORD);
...
```

### ec\_cert\_sign()

`ec_err_t ec_cert_sign(ec_cert_t *c, ec_cert_t *signer);`

Sign a certificate using another certificate. Returns a nonzero error code on failure.

The signer must have a valid secret key available, and both certificates must pass the following checks prior to signing:

```c
ec_cert_check(NULL, c, EC_CHECK_CERT);
ec_cert_check(NULL, signer, EC_CHECK_CERT | EC_CHECK_SECRET);
```

If the certificate's validity falls outside that of the signer, the appropriate timestamp on the certificate will be adjusted to match that of the signer.

```c
#include <ec.h>
...
if(ec_cert_sign(c, signer) != 0) {
    //signing succeeded
}
...
```

### ec\_cert\_check()

`ec_err_t ec_cert_check(ec_ctx_t *ctx, ec_cert_t *c, int flags);`

Ensure that a certificate passes a given set of tests. Returns a nonzero error code on failure.

All tests which require a valid trust chain to be present must also provide a context where the trust chain may be found. Tests which apply only to the certificate may pass `NULL` instead.

The `flags` parameter is used to set which tests are run, according to the following table. Checks are run in the order that they are listed here.

| Flag               | Implies          | Context Required? | Tests                                                                                                                                                                                                                                                                             |
| ------------------ | ---------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| EC\_CHECK\_CERT    |                  | No                | Certificate is the correct version, a valid public key is present, the current time falls within the certificate's validity period, any records present are of a valid length, any section records have a NULL-terminated string key.                                             |
| EC\_CHECK\_SECRET  |                  | No                | A secret key is present                                                                                                                                                                                                                                                           |
| EC\_CHECK\_SIGN    |                  | Yes1              | Signer ID is present, signature is present, signer is available, validity period falls within signer validity period, signature passes cryptographic validation.                                                                                                                  |
| EC\_CHECK\_CHAIN2  | EC\_CHECK\_SIGN  | Yes               | Certificate is not self-signed, signer also passes every check that certificate is required to pass, except for EC\_CHECK\_SECRET.                                                                                                                                                |
| EC\_CHECK\_ROLE    | EC\_CHECK\_CHAIN | Yes               | Grant records have a valid string key, grant records match or are a subset of the signer's grant records unless EC\_CERT\_TRUSTED is set, role records have a valid string key, role records match or are a subset of the signer's grant records unless EC\_CERT\_TRUSTED is set. |
| EC\_CHECK\_REQUIRE |                  | Yes               | A validator function has been set, all records with EC\_RECORD\_REQUIRE are considered acceptable by the validator.                                                                                                                                                               |
| EC\_CHECK\_ALL     |                  | Yes               | Every check listed above except for EC\_CHECK\_SECRET.                                                                                                                                                                                                                            |

1 Context is not required if the certificate is self-signed.\
2 `EC_CHECK_CHAIN` always passes if `EC_CERT_TRUSTED` is set on the certificate.

```c
#include <ec.h>
...
if(ec_cert_check(ctx, c, EC_CHECK_CERT | EC_CHECK_ROLE) != 0) {
    //certificate passes the defined checks
}
...
```

### ec\_cert\_id()

`ec_id_t ec_cert_id(ec_cert_t *c);`

Get a unique ID for a certificate. This ID is based on the certificate's public key, and will not change if the certificate is modified by e.g. signing, adding records etc.

This ID is used for things like retrieving a certificate from a context store, identifying a signer, etc.

```c
#include <ec.h>
...
ec_id_t id = ec_cert_id(c);
...
```

### ec\_cert\_records()

`ec_record_t *ec_cert_records(ec_cert_t *c);`

Get the records list for a certificate. Returns NULL if there are no records present.

```c
#include <ec.h>
...
ec_record_t *list = ec_cert_records(c);
if(list == NULL) {
    //no records present
}
...
```

### ec\_cert\_lock()

`ec_err_t ec_cert_lock(ec_cert_t *c, char *password);`

Encrypt a certificate's secret key using a password. Returns zero on success, or a nonzero error code otherwise.

If the secret key is encrypted successfully, EC\_CERT\_CRYPTSK will be set.

```c
#include <ec.h>
...
if(ec_cert_lock(c, "mySuperSecretPassword") != 0) {
    //unable to encrypt secret key
}
...
```

### ec\_cert\_unlock()

`ec_err_t ec_cert_unlock(ec_cert_t *c, char *password);`

Decrypt a certificate's secret key using a password. Returns zero on success, or a nonzero error code otherwise. If the secret key is not encrypted, then this function will take no action and return zero anyway.

If the secret key is decrypted successfully, then EC\_CERT\_CRYPTSK will be cleared.

Note that using an incorrect password is not considered an error, but the resulting secret key will be unusable, and any attempts to sign something with it will fail.

```c
#include <ec.h>
...
if(ec_cert_unlock(c, "mySuperSecretPassword") != 0) {
    //unable to decrypt secret key
}
...
```
