#define DTLS_VERSION 0xfefd /* DTLS v1.2 */
#endif
+#ifdef DTLS_X509
+#define DTLS_MAX_CERT_SIZE 1400
+#endif
+
typedef enum dtls_credentials_type_t {
DTLS_PSK_HINT, DTLS_PSK_IDENTITY, DTLS_PSK_KEY
} dtls_credentials_type_t;
* session.
* @return @c 0 if result is set, or less than zero on error.
*/
- int (*get_ecdsa_key)(struct dtls_context_t *ctx,
+ int (*get_ecdsa_key)(struct dtls_context_t *ctx,
const session_t *session,
const dtls_ecc_key_t **result);
+
/**
* Called during handshake to check the peer's pubic key in this
* session. If the public key matches the session and should be
- * considerated valid the return value must be @c 0. If not valid,
+ * considered valid the return value must be @c 0. If not valid,
* the return value must be less than zero.
*
* If ECDSA should not be supported, set this pointer to NULL.
* return dtls_alert_fatal_create(DTLS_ALERT_CERTIFICATE_UNKNOWN);
* return dtls_alert_fatal_create(DTLS_ALERT_UNKNOWN_CA);
*/
- int (*verify_ecdsa_key)(struct dtls_context_t *ctx,
+ int (*verify_ecdsa_key)(struct dtls_context_t *ctx,
const session_t *session,
const unsigned char *other_pub_x,
const unsigned char *other_pub_y,
size_t key_size);
#endif /* DTLS_ECC */
+#ifdef DTLS_X509
+ /**
+ * Called during handshake to get the server's or client's ecdsa
+ * key used to authenticate this server or client in this
+ * session. If found, the key must be stored in @p result and
+ * the return value must be @c 0. If not found, @p result is
+ * undefined and the return value must be less than zero.
+ *
+ * If ECDSA should not be supported, set this pointer to NULL.
+ *
+ * Implement this if you want to provide your own certificate to
+ * the other peer. This is mandatory for a server providing X.509
+ * support and optional for a client. A client doing DTLS client
+ * authentication has to implementing this callback.
+ *
+ * @param ctx The current dtls context.
+ * @param session The session where the key will be used.
+ * @param result Must be set to the key object to used for the given
+ * session.
+ * @return @c 0 if result is set, or less than zero on error.
+ */
+ int (*get_x509_key)(struct dtls_context_t *ctx,
+ const session_t *session,
+ const dtls_ecc_key_t **result);
+ /**
+ * Called during handshake to get the server's or client's
+ * certificate used to authenticate this server or client in this
+ * session. If found, the certificate must be stored in @p cert and
+ * the return value must be @c 0. If not found, @p cert is
+ * undefined and the return value must be less than zero.
+ *
+ * If X.509 should not be supported, set this pointer to NULL.
+ *
+ * Implement this if you want to provide your own certificate to
+ * the other peer. This is mandatory for a server providing X.509
+ * support and optional for a client. A client doing DTLS client
+ * authentication has to implementing this callback.
+ *
+ * @param ctx The current dtls context.
+ * @param session The session where the certificate will be used.
+ * @param cert Must be set to the certificate object to used for
+ * the given session.
+ * @param cert_size Size of certificate in bytes.
+ * @return @c 0 if result is set, or less than zero on error.
+ */
+ int (*get_x509_cert)(struct dtls_context_t *ctx,
+ const session_t *session,
+ const unsigned char **cert,
+ size_t *cert_size);
+
+ /**
+ * Called during handshake to check the peer's certificate in this
+ * session. If the certificate matches the session and is valid the
+ * return value must be @c 0. If not valid, the return value must be
+ * less than zero.
+ *
+ * If X.509 should not be supported, set this pointer to NULL.
+ *
+ * Implement this if you want to verify the other peers certificate.
+ * This is mandatory for a DTLS client doing based X.509
+ * authentication. A server implementing this will request the
+ * client to do DTLS client authentication.
+ *
+ * @param ctx The current dtls context.
+ * @param session The session where the key will be used.
+ * @param cert Peer's certificate to check.
+ * @param cert_size Size of certificate in bytes.
+ * @param x Allocated memory to store peer's public key part x.
+ * @param x_size Size of allocated memory to store peer's public key part x.
+ * @param y Allocated memory to store peer's public key part y.
+ * @param y_size Size of allocated memory to store peer's public key part y.
+ * @return @c 0 if public key matches, or less than zero on error.
+ * error codes:
+ * return dtls_alert_fatal_create(DTLS_ALERT_BAD_CERTIFICATE);
+ * return dtls_alert_fatal_create(DTLS_ALERT_UNSUPPORTED_CERTIFICATE);
+ * return dtls_alert_fatal_create(DTLS_ALERT_CERTIFICATE_REVOKED);
+ * return dtls_alert_fatal_create(DTLS_ALERT_CERTIFICATE_EXPIRED);
+ * return dtls_alert_fatal_create(DTLS_ALERT_CERTIFICATE_UNKNOWN);
+ * return dtls_alert_fatal_create(DTLS_ALERT_UNKNOWN_CA);
+ */
+ int (*verify_x509_cert)(struct dtls_context_t *ctx,
+ const session_t *session,
+ const unsigned char *cert,
+ size_t cert_size,
+ unsigned char *x,
+ size_t x_size,
+ unsigned char *y,
+ size_t y_size);
+
+ /**
+ * Called during handshake to check if certificate format should be X.509
+ *
+ * If X.509 should not be supported, set this pointer to NULL.
+ *
+ * @param ctx The current dtls context.
+ * @return @c 0 if certificate format should be X.509, or less than zero on error.
+ */
+ int (*is_x509_active)(struct dtls_context_t *ctx);
+#endif /* DTLS_X509 */
+
} dtls_handler_t;
/** Holds global information of the DTLS engine. */
#define dtls_get_app_data(CTX) ((CTX)->app)
/** Sets the callback handler object for @p ctx to @p h. */
-static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
+INLINE_API void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
ctx->h = h;
}
#define DTLS_CT_HANDSHAKE 22
#define DTLS_CT_APPLICATION_DATA 23
+#if defined(_MSC_VER)
+#define PACKED_STRUCT_START __pragma(pack(push,1)); typedef struct
+#define PACKED_STRUCT_END __pragma(pack(pop))
+#else
+#define PACKED_STRUCT_START typedef struct __attribute__((__packed__))
+#define PACKED_STRUCT_END
+#endif
+
/** Generic header structure of the DTLS record layer. */
-typedef struct __attribute__((__packed__)) {
+PACKED_STRUCT_START {
uint8 content_type; /**< content type of the included message */
uint16 version; /**< Protocol version */
uint16 epoch; /**< counter for cipher state changes */
uint16 length; /**< length of the following fragment */
/* fragment */
} dtls_record_header_t;
+PACKED_STRUCT_END;
/* Handshake types */
#define DTLS_HT_FINISHED 20
/** Header structure for the DTLS handshake protocol. */
-typedef struct __attribute__((__packed__)) {
+PACKED_STRUCT_START {
uint8 msg_type; /**< Type of handshake message (one of DTLS_HT_) */
uint24 length; /**< length of this message */
uint16 message_seq; /**< Message sequence number */
uint24 fragment_length; /**< Fragment length. */
/* body */
} dtls_handshake_header_t;
+PACKED_STRUCT_END;
/** Structure of the Client Hello message. */
-typedef struct __attribute__((__packed__)) {
+PACKED_STRUCT_START {
uint16 version; /**< Client version */
uint32 gmt_random; /**< GMT time of the random byte creation */
unsigned char random[28]; /**< Client random bytes */
/* cipher suite (2 to 2^16 -1 bytes) */
/* compression method */
} dtls_client_hello_t;
+PACKED_STRUCT_END;
/** Structure of the Hello Verify Request. */
-typedef struct __attribute__((__packed__)) {
+PACKED_STRUCT_START {
uint16 version; /**< Server version */
uint8 cookie_length; /**< Length of the included cookie */
uint8 cookie[]; /**< up to 32 bytes making up the cookie */
} dtls_hello_verify_t;
+PACKED_STRUCT_END;
#if 0
/**