Skip to content

Commit 660480d

Browse files
committed
expose new FIPS related APIs
* Ability to instantiate the FIPS default `crypto_provider` using a new function `rustls_default_fips_provider()`, available only when the fips feature is activated. * Ability to determine if a given `crypto_provider` is in FIPS mode using a new function `rustls_crypto_provider_fips()`. * Ability to determine if a given `rustls_client_config` would create connections that are FIPS compatible with a new function `rustls_client_config_fips()`. * Ability to determine if a given `rustls_server_config` would create connections that are FIPS compatible with a new function `rustls_server_config_fips()`. * Ability to determine if a given `rustls_connection` was created from a `rustls_client_config` that was FIPS enabled with a new function `rustls_connection_fips()`. Doing equivalent for a server connection is not presently supported upstream (will be fixed next release).
1 parent 75fd188 commit 660480d

File tree

6 files changed

+136
-1
lines changed

6 files changed

+136
-1
lines changed

cbindgen.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ include = ["rustls_tls_version"]
1414
"feature = read_buf" = "DEFINE_READ_BUF"
1515
"feature = aws-lc-rs" = "DEFINE_AWS_LC_RS"
1616
"feature = ring" = "DEFINE_RING"
17+
"feature = fips" = "DEFINE_FIPS"
1718

1819
[parse.expand]
1920
crates = ["rustls-ffi"]
20-
features = ["read_buf", "aws-lc-rs", "ring"]
21+
features = ["read_buf", "aws-lc-rs", "ring", "fips"]

src/client.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,19 @@ impl rustls_client_config_builder {
582582
}
583583

584584
impl rustls_client_config {
585+
/// Returns true if a `rustls_connection` created from the `rustls_client_config` will
586+
/// operate in FIPS mode.
587+
///
588+
/// This is different from `rustls_crypto_provider_fips` which is concerned
589+
/// only with cryptography, whereas this also covers TLS-level configuration that NIST
590+
/// recommends, as well as ECH HPKE suites if applicable.
591+
#[no_mangle]
592+
pub extern "C" fn rustls_client_config_fips(config: *const rustls_client_config) -> bool {
593+
ffi_panic_boundary! {
594+
try_ref_from_ptr!(config).fips()
595+
}
596+
}
597+
585598
/// "Free" a `rustls_client_config` previously returned from
586599
/// `rustls_client_config_builder_build`.
587600
///

src/connection.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,24 @@ impl rustls_connection {
613613
}
614614
}
615615

616+
/// Returns true if the `rustls_connection` was made with a `rustls_client_config`
617+
/// that is FIPS compatible.
618+
///
619+
/// This is different from `rustls_crypto_provider_fips` which is concerned
620+
/// only with cryptography, whereas this also covers TLS-level configuration that NIST
621+
/// recommends, as well as ECH HPKE suites if applicable.
622+
#[no_mangle]
623+
pub extern "C" fn rustls_connection_fips(conn: *const rustls_connection) -> bool {
624+
ffi_panic_boundary! {
625+
let conn = try_ref_from_ptr!(conn);
626+
match &conn.conn {
627+
rustls::Connection::Client(c) => c.fips(),
628+
// TODO(XXX): investigate why there isn't a ServerConnection::fips().
629+
_ => false,
630+
}
631+
}
632+
}
633+
616634
/// Free a rustls_connection. Calling with NULL is fine.
617635
/// Must not be called twice with the same value.
618636
#[no_mangle]

src/crypto_provider.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,26 @@ pub extern "C" fn rustls_aws_lc_rs_crypto_provider() -> *const rustls_crypto_pro
248248
}
249249
}
250250

251+
/// Return a `rustls_crypto_provider` that uses FIPS140-3 approved cryptography.
252+
///
253+
/// Using this function expresses in your code that you require FIPS-approved cryptography,
254+
/// and will not compile if you make a mistake with cargo features.
255+
///
256+
/// See the upstream [rustls FIPS documentation][FIPS] for more information.
257+
///
258+
/// The caller owns the returned `rustls_crypto_provider` and must free it using
259+
/// `rustls_crypto_provider_free`.
260+
///
261+
/// [FIPS]: https://docs.rs/rustls/latest/rustls/manual/_06_fips/index.html
262+
#[no_mangle]
263+
#[cfg(feature = "fips")]
264+
pub extern "C" fn rustls_default_fips_provider() -> *const rustls_crypto_provider {
265+
ffi_panic_boundary! {
266+
Arc::into_raw(Arc::new(rustls::crypto::default_fips_provider()))
267+
as *const rustls_crypto_provider
268+
}
269+
}
270+
251271
/// Retrieve a pointer to the process default `rustls_crypto_provider`.
252272
///
253273
/// This may return `NULL` if no process default provider has been set using
@@ -364,6 +384,19 @@ pub extern "C" fn rustls_crypto_provider_random(
364384
}
365385
}
366386

387+
/// Returns true if the `rustls_crypto_provider` is operating in FIPS mode.
388+
///
389+
/// This covers only the cryptographic parts of FIPS approval. There are also
390+
/// TLS protocol-level recommendations made by NIST. You should prefer to call
391+
/// `rustls_client_config_fips` or `rustls_server_config_fips` which take these
392+
/// into account.
393+
#[no_mangle]
394+
pub extern "C" fn rustls_crypto_provider_fips(provider: *const rustls_crypto_provider) -> bool {
395+
ffi_panic_boundary! {
396+
try_ref_from_ptr!(provider).fips()
397+
}
398+
}
399+
367400
/// Frees the `rustls_crypto_provider`.
368401
///
369402
/// Calling with `NULL` is fine.

src/rustls.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,6 +1758,16 @@ rustls_result rustls_client_config_builder_build(struct rustls_client_config_bui
17581758
*/
17591759
void rustls_client_config_builder_free(struct rustls_client_config_builder *config);
17601760

1761+
/**
1762+
* Returns true if a `rustls_connection` created from the `rustls_client_config` will
1763+
* operate in FIPS mode.
1764+
*
1765+
* This is different from `rustls_crypto_provider_fips` which is concerned
1766+
* only with cryptography, whereas this also covers TLS-level configuration that NIST
1767+
* recommends, as well as ECH HPKE suites if applicable.
1768+
*/
1769+
bool rustls_client_config_fips(const struct rustls_client_config *config);
1770+
17611771
/**
17621772
* "Free" a `rustls_client_config` previously returned from
17631773
* `rustls_client_config_builder_build`.
@@ -2047,6 +2057,16 @@ rustls_result rustls_connection_read_2(struct rustls_connection *conn,
20472057
size_t *out_n);
20482058
#endif
20492059

2060+
/**
2061+
* Returns true if the `rustls_connection` was made with a `rustls_client_config`
2062+
* that is FIPS compatible.
2063+
*
2064+
* This is different from `rustls_crypto_provider_fips` which is concerned
2065+
* only with cryptography, whereas this also covers TLS-level configuration that NIST
2066+
* recommends, as well as ECH HPKE suites if applicable.
2067+
*/
2068+
bool rustls_connection_fips(const struct rustls_connection *conn);
2069+
20502070
/**
20512071
* Free a rustls_connection. Calling with NULL is fine.
20522072
* Must not be called twice with the same value.
@@ -2172,6 +2192,23 @@ const struct rustls_crypto_provider *rustls_ring_crypto_provider(void);
21722192
const struct rustls_crypto_provider *rustls_aws_lc_rs_crypto_provider(void);
21732193
#endif
21742194

2195+
#if defined(DEFINE_FIPS)
2196+
/**
2197+
* Return a `rustls_crypto_provider` that uses FIPS140-3 approved cryptography.
2198+
*
2199+
* Using this function expresses in your code that you require FIPS-approved cryptography,
2200+
* and will not compile if you make a mistake with cargo features.
2201+
*
2202+
* See the upstream [rustls FIPS documentation][FIPS] for more information.
2203+
*
2204+
* The caller owns the returned `rustls_crypto_provider` and must free it using
2205+
* `rustls_crypto_provider_free`.
2206+
*
2207+
* [FIPS]: https://docs.rs/rustls/latest/rustls/manual/_06_fips/index.html
2208+
*/
2209+
const struct rustls_crypto_provider *rustls_default_fips_provider(void);
2210+
#endif
2211+
21752212
/**
21762213
* Retrieve a pointer to the process default `rustls_crypto_provider`.
21772214
*
@@ -2233,6 +2270,16 @@ rustls_result rustls_crypto_provider_random(const struct rustls_crypto_provider
22332270
uint8_t *buff,
22342271
size_t len);
22352272

2273+
/**
2274+
* Returns true if the `rustls_crypto_provider` is operating in FIPS mode.
2275+
*
2276+
* This covers only the cryptographic parts of FIPS approval. There are also
2277+
* TLS protocol-level recommendations made by NIST. You should prefer to call
2278+
* `rustls_client_config_fips` or `rustls_server_config_fips` which take these
2279+
* into account.
2280+
*/
2281+
bool rustls_crypto_provider_fips(const struct rustls_crypto_provider *provider);
2282+
22362283
/**
22372284
* Frees the `rustls_crypto_provider`.
22382285
*
@@ -2497,6 +2544,16 @@ rustls_result rustls_server_config_builder_set_certified_keys(struct rustls_serv
24972544
rustls_result rustls_server_config_builder_build(struct rustls_server_config_builder *builder,
24982545
const struct rustls_server_config **config_out);
24992546

2547+
/**
2548+
* Returns true if a `rustls_connection` created from the `rustls_server_config` will
2549+
* operate in FIPS mode.
2550+
*
2551+
* This is different from `rustls_crypto_provider_fips` which is concerned
2552+
* only with cryptography, whereas this also covers TLS-level configuration that NIST
2553+
* recommends, as well as ECH HPKE suites if applicable.
2554+
*/
2555+
bool rustls_server_config_fips(const struct rustls_server_config *config);
2556+
25002557
/**
25012558
* "Free" a rustls_server_config previously returned from
25022559
* rustls_server_config_builder_build.

src/server.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,19 @@ impl rustls_server_config_builder {
377377
}
378378

379379
impl rustls_server_config {
380+
/// Returns true if a `rustls_connection` created from the `rustls_server_config` will
381+
/// operate in FIPS mode.
382+
///
383+
/// This is different from `rustls_crypto_provider_fips` which is concerned
384+
/// only with cryptography, whereas this also covers TLS-level configuration that NIST
385+
/// recommends, as well as ECH HPKE suites if applicable.
386+
#[no_mangle]
387+
pub extern "C" fn rustls_server_config_fips(config: *const rustls_server_config) -> bool {
388+
ffi_panic_boundary! {
389+
try_ref_from_ptr!(config).fips()
390+
}
391+
}
392+
380393
/// "Free" a rustls_server_config previously returned from
381394
/// rustls_server_config_builder_build.
382395
///

0 commit comments

Comments
 (0)