@@ -26,12 +26,15 @@ use axum::routing::{get, post};
2626use axum:: Router ;
2727use clap:: Parser ;
2828use confargs:: { prefix_char_filter, Toml } ;
29+ #[ cfg( debug_assertions) ]
30+ use const_oid:: db:: rfc5280:: { ID_CE_BASIC_CONSTRAINTS , ID_CE_KEY_USAGE } ;
2931use const_oid:: db:: rfc5280:: {
30- ID_CE_BASIC_CONSTRAINTS , ID_CE_EXT_KEY_USAGE , ID_CE_KEY_USAGE , ID_CE_SUBJECT_ALT_NAME ,
31- ID_KP_CLIENT_AUTH , ID_KP_SERVER_AUTH ,
32+ ID_CE_EXT_KEY_USAGE , ID_CE_SUBJECT_ALT_NAME , ID_KP_CLIENT_AUTH , ID_KP_SERVER_AUTH ,
3233} ;
3334use const_oid:: db:: rfc5912:: ID_EXTENSION_REQ ;
34- use der:: asn1:: { GeneralizedTime , Ia5StringRef , UIntRef } ;
35+ #[ cfg( debug_assertions) ]
36+ use der:: asn1:: GeneralizedTime ;
37+ use der:: asn1:: { Ia5StringRef , UIntRef } ;
3538use der:: { Decode , Encode , Sequence } ;
3639use ext:: kvm:: Kvm ;
3740use ext:: sgx:: Sgx ;
@@ -48,7 +51,9 @@ use tower_http::LatencyUnit;
4851use tracing:: { debug, Level } ;
4952use x509:: attr:: Attribute ;
5053use x509:: ext:: pkix:: name:: GeneralName ;
51- use x509:: ext:: pkix:: { BasicConstraints , ExtendedKeyUsage , KeyUsage , KeyUsages , SubjectAltName } ;
54+ #[ cfg( debug_assertions) ]
55+ use x509:: ext:: pkix:: { BasicConstraints , KeyUsage , KeyUsages } ;
56+ use x509:: ext:: pkix:: { ExtendedKeyUsage , SubjectAltName } ;
5257use x509:: name:: RdnSequence ;
5358use x509:: request:: { CertReq , ExtensionReq } ;
5459use x509:: time:: { Time , Validity } ;
@@ -80,6 +85,7 @@ struct Args {
8085 #[ clap( short, long, env = "ROCKET_ADDRESS" , default_value = "::" ) ]
8186 addr : IpAddr ,
8287
88+ #[ cfg( debug_assertions) ]
8389 #[ clap( short, long, env = "RENDER_EXTERNAL_HOSTNAME" ) ]
8490 host : Option < String > ,
8591
@@ -141,11 +147,22 @@ impl State {
141147
142148 // Validate the syntax of the files.
143149 PrivateKeyInfo :: from_der ( key. as_ref ( ) ) ?;
150+ #[ cfg( debug_assertions) ]
144151 Certificate :: from_der ( crt. as_ref ( ) ) ?;
152+ #[ cfg( not( debug_assertions) ) ]
153+ {
154+ let cert = Certificate :: from_der ( crt. as_ref ( ) ) ?;
155+ let iss = & cert. tbs_certificate ;
156+ if iss. issuer_unique_id == iss. subject_unique_id && iss. issuer == iss. subject {
157+ // A self-signed certificate is not appropriate for Release mode.
158+ return Err ( anyhow ! ( "invalid certificate" ) ) ;
159+ }
160+ }
145161
146162 Ok ( State { crt, san, key } )
147163 }
148164
165+ #[ cfg( debug_assertions) ]
149166 pub fn generate ( san : Option < String > , hostname : & str ) -> anyhow:: Result < Self > {
150167 use const_oid:: db:: rfc5912:: SECP_256_R_1 as P256 ;
151168
@@ -219,6 +236,8 @@ async fn main() -> anyhow::Result<()> {
219236 let args = confargs:: args :: < Toml > ( prefix_char_filter :: < '@' > )
220237 . context ( "Failed to parse config" )
221238 . map ( Args :: parse_from) ?;
239+
240+ #[ cfg( debug_assertions) ]
222241 let state = match ( args. key , args. crt , args. host ) {
223242 ( None , None , Some ( host) ) => State :: generate ( args. san , & host) ?,
224243 ( Some ( key) , Some ( crt) , _) => State :: load ( args. san , key, crt) ?,
@@ -228,6 +247,15 @@ async fn main() -> anyhow::Result<()> {
228247 }
229248 } ;
230249
250+ #[ cfg( not( debug_assertions) ) ]
251+ let state = match ( args. key , args. crt ) {
252+ ( Some ( key) , Some ( crt) ) => State :: load ( args. san , key, crt) ?,
253+ _ => {
254+ eprintln ! ( "Specify the public key `--crt` and private key `--key`.\n Run with `--help` for more information." ) ;
255+ return Err ( anyhow ! ( "invalid configuration" ) ) ;
256+ }
257+ } ;
258+
231259 #[ cfg( not( target_os = "wasi" ) ) ]
232260 {
233261 use std:: net:: SocketAddr ;
@@ -316,6 +344,14 @@ fn attest_request(
316344 StatusCode :: BAD_REQUEST
317345 } ) ?;
318346
347+ let dbg = if cfg ! ( debug_assertions) {
348+ // If the issuer is self-signed, we are in debug mode.
349+ let iss = & issuer. tbs_certificate ;
350+ iss. issuer_unique_id == iss. subject_unique_id && iss. issuer == iss. subject
351+ } else {
352+ false
353+ } ;
354+
319355 let mut extensions = Vec :: new ( ) ;
320356 let mut attested = false ;
321357 for Attribute { oid, values } in info. attributes . iter ( ) {
@@ -329,16 +365,11 @@ fn attest_request(
329365 StatusCode :: BAD_REQUEST
330366 } ) ?;
331367 for ext in Vec :: from ( ereq) {
332- // If the issuer is self-signed, we are in debug mode.
333- let iss = & issuer. tbs_certificate ;
334- let dbg = iss. issuer_unique_id == iss. subject_unique_id ;
335- let dbg = dbg && iss. issuer == iss. subject ;
336-
337368 // Validate the extension.
338369 let ( copy, att) = match ext. extn_id {
339- Kvm :: OID => ( Kvm :: default ( ) . verify ( & info, & ext, dbg) , Kvm :: ATT ) ,
340- Sgx :: OID => ( Sgx :: default ( ) . verify ( & info, & ext, dbg) , Sgx :: ATT ) ,
341- Snp :: OID => ( Snp :: default ( ) . verify ( & info, & ext, dbg) , Snp :: ATT ) ,
370+ Kvm :: OID => ( Kvm :: default ( ) . verify ( & info, & ext, & dbg) , Kvm :: ATT ) ,
371+ Sgx :: OID => ( Sgx :: default ( ) . verify ( & info, & ext, & dbg) , Sgx :: ATT ) ,
372+ Snp :: OID => ( Snp :: default ( ) . verify ( & info, & ext, & dbg) , Snp :: ATT ) ,
342373 oid => {
343374 debug ! ( "extension `{oid}` is unsupported" ) ;
344375 return Err ( StatusCode :: BAD_REQUEST ) ;
@@ -471,16 +502,22 @@ async fn attest(
471502#[ cfg( test) ]
472503mod tests {
473504 mod attest {
474- use crate :: ext:: { kvm:: Kvm , sgx:: Sgx , snp:: Snp , ExtVerifier } ;
505+ use crate :: ext:: { kvm:: Kvm , ExtVerifier } ;
506+ #[ cfg( debug_assertions) ]
507+ use crate :: ext:: { sgx:: Sgx , snp:: Snp } ;
475508 use crate :: * ;
476- use const_oid:: db:: rfc5912:: { ID_EXTENSION_REQ , SECP_256_R_1 , SECP_384_R_1 } ;
509+ #[ cfg( debug_assertions) ]
510+ use const_oid:: db:: rfc5912:: SECP_384_R_1 ;
511+ use const_oid:: db:: rfc5912:: { ID_EXTENSION_REQ , SECP_256_R_1 } ;
477512 use const_oid:: ObjectIdentifier ;
478513 use der:: { AnyRef , Encode } ;
479514 use x509:: attr:: Attribute ;
480515 use x509:: request:: { CertReq , CertReqInfo , ExtensionReq } ;
516+ #[ cfg( debug_assertions) ]
481517 use x509:: PkiPath ;
482518 use x509:: { ext:: Extension , name:: RdnSequence } ;
483519
520+ #[ cfg( debug_assertions) ]
484521 use axum:: response:: Response ;
485522 use http:: header:: CONTENT_TYPE ;
486523 use http:: Request ;
@@ -490,17 +527,34 @@ mod tests {
490527
491528 fn certificates_state ( ) -> State {
492529 #[ cfg( not( target_os = "wasi" ) ) ]
493- return State :: load ( None , "testdata/ca.key" , "testdata/ca.crt" )
494- . expect ( "failed to load state" ) ;
530+ {
531+ #[ cfg( debug_assertions) ]
532+ return State :: load ( None , "testdata/ca.key" , "testdata/ca.crt" )
533+ . expect ( "failed to load state" ) ;
534+ #[ cfg( not( debug_assertions) ) ]
535+ return State :: load ( None , "testdata/test.key" , "testdata/test.crt" )
536+ . expect ( "failed to load state" ) ;
537+ }
538+
495539 #[ cfg( target_os = "wasi" ) ]
496540 {
497- let crt = std:: io:: BufReader :: new ( include_bytes ! ( "../testdata/ca.crt" ) . as_slice ( ) ) ;
498- let key = std:: io:: BufReader :: new ( include_bytes ! ( "../testdata/ca.key" ) . as_slice ( ) ) ;
541+ let ( crt, key) = if cfg ! ( debug_assertions) {
542+ (
543+ std:: io:: BufReader :: new ( include_bytes ! ( "../testdata/ca.crt" ) . as_slice ( ) ) ,
544+ std:: io:: BufReader :: new ( include_bytes ! ( "../testdata/ca.key" ) . as_slice ( ) ) ,
545+ )
546+ } else {
547+ (
548+ std:: io:: BufReader :: new ( include_bytes ! ( "../testdata/test.crt" ) . as_slice ( ) ) ,
549+ std:: io:: BufReader :: new ( include_bytes ! ( "../testdata/test.key" ) . as_slice ( ) ) ,
550+ )
551+ } ;
499552
500553 State :: read ( None , key, crt) . expect ( "failed to load state" )
501554 }
502555 }
503556
557+ #[ cfg( debug_assertions) ]
504558 fn hostname_state ( ) -> State {
505559 State :: generate ( None , "localhost" ) . unwrap ( )
506560 }
@@ -534,6 +588,7 @@ mod tests {
534588 }
535589 }
536590
591+ #[ cfg( debug_assertions) ]
537592 async fn attest_response ( state : State , response : Response , multi : bool ) {
538593 let body = hyper:: body:: to_bytes ( response. into_body ( ) ) . await . unwrap ( ) ;
539594
@@ -591,10 +646,18 @@ mod tests {
591646 . unwrap ( ) ;
592647
593648 let response = app ( certificates_state ( ) ) . oneshot ( request) . await . unwrap ( ) ;
594- assert_eq ! ( response. status( ) , StatusCode :: OK ) ;
595- attest_response ( certificates_state ( ) , response, multi) . await ;
649+ #[ cfg( debug_assertions) ]
650+ {
651+ assert_eq ! ( response. status( ) , StatusCode :: OK ) ;
652+ attest_response ( certificates_state ( ) , response, multi) . await ;
653+ }
654+ #[ cfg( not( debug_assertions) ) ]
655+ {
656+ assert_eq ! ( response. status( ) , StatusCode :: BAD_REQUEST ) ;
657+ }
596658 }
597659
660+ #[ cfg( debug_assertions) ]
598661 #[ rstest]
599662 #[ case( PKCS10 , false ) ]
600663 #[ case( BUNDLE , true ) ]
@@ -621,6 +684,7 @@ mod tests {
621684
622685 // Though similar to the above test, this is the only test which
623686 // actually sends many CSRs, versus an array of just one CSR.
687+ #[ cfg( debug_assertions) ]
624688 #[ tokio:: test]
625689 async fn kvm_hostname_many_certs ( ) {
626690 let ext = Extension {
@@ -658,6 +722,7 @@ mod tests {
658722 assert_eq ! ( output. issued. len( ) , five_crs. len( ) ) ;
659723 }
660724
725+ #[ cfg( debug_assertions) ]
661726 #[ rstest]
662727 #[ case( PKCS10 , false ) ]
663728 #[ case( BUNDLE , true ) ]
@@ -686,6 +751,7 @@ mod tests {
686751 }
687752 }
688753
754+ #[ cfg( debug_assertions) ]
689755 #[ rstest]
690756 #[ case( PKCS10 , false ) ]
691757 #[ case( BUNDLE , true ) ]
@@ -715,6 +781,7 @@ mod tests {
715781 }
716782 }
717783
784+ #[ cfg( debug_assertions) ]
718785 #[ rstest]
719786 #[ case( PKCS10 , false ) ]
720787 #[ case( BUNDLE , true ) ]
@@ -745,6 +812,7 @@ mod tests {
745812 attest_response ( certificates_state ( ) , response, multi) . await ;
746813 }
747814
815+ #[ cfg( debug_assertions) ]
748816 #[ rstest]
749817 #[ case( PKCS10 , false ) ]
750818 #[ case( BUNDLE , true ) ]
@@ -776,6 +844,7 @@ mod tests {
776844 attest_response ( state, response, multi) . await ;
777845 }
778846
847+ #[ cfg( debug_assertions) ]
779848 #[ rstest]
780849 #[ case( PKCS10 , false ) ]
781850 #[ case( BUNDLE , true ) ]
@@ -792,6 +861,7 @@ mod tests {
792861 assert_eq ! ( response. status( ) , StatusCode :: UNAUTHORIZED ) ;
793862 }
794863
864+ #[ cfg( debug_assertions) ]
795865 #[ tokio:: test]
796866 async fn err_no_attestation_hostname ( ) {
797867 let request = Request :: builder ( )
@@ -805,6 +875,7 @@ mod tests {
805875 assert_eq ! ( response. status( ) , StatusCode :: UNAUTHORIZED ) ;
806876 }
807877
878+ #[ cfg( debug_assertions) ]
808879 #[ rstest]
809880 #[ case( false ) ]
810881 #[ case( true ) ]
@@ -820,6 +891,7 @@ mod tests {
820891 assert_eq ! ( response. status( ) , StatusCode :: BAD_REQUEST ) ;
821892 }
822893
894+ #[ cfg( debug_assertions) ]
823895 #[ tokio:: test]
824896 async fn err_empty_body ( ) {
825897 let request = Request :: builder ( )
@@ -832,6 +904,7 @@ mod tests {
832904 assert_eq ! ( response. status( ) , StatusCode :: BAD_REQUEST ) ;
833905 }
834906
907+ #[ cfg( debug_assertions) ]
835908 #[ tokio:: test]
836909 async fn err_bad_body ( ) {
837910 let request = Request :: builder ( )
@@ -844,6 +917,7 @@ mod tests {
844917 assert_eq ! ( response. status( ) , StatusCode :: BAD_REQUEST ) ;
845918 }
846919
920+ #[ cfg( debug_assertions) ]
847921 #[ tokio:: test]
848922 async fn err_bad_csr_sig ( ) {
849923 let mut cr = cr ( SECP_256_R_1 , vec ! [ ] , true ) ;
0 commit comments