11import type { Config as QuicheConfig } from './native/types' ;
22import { quiche } from './native' ;
3-
3+ import * as errors from './errors' ;
44
55type QUICConfig = {
66 /**
@@ -133,11 +133,18 @@ const textDecoder = new TextDecoder('utf-8');
133133const textEncoder = new TextEncoder ( ) ;
134134
135135function buildQuicheConfig ( config : QUICConfig ) : QuicheConfig {
136-
137- // This will be passed in as a Optional<Uint8Array>
138-
139- // This is a concatenated certificate authority certificates in
140- // PEM format, separated by `\n`
136+ if ( config . key != null && config . cert == null ) {
137+ throw new errors . ErrorQUICConfig ( 'The cert option must be set when key is set' ) ;
138+ } else if ( config . key == null && config . cert != null ) {
139+ throw new errors . ErrorQUICConfig ( 'The key option must be set when cert is set' ) ;
140+ } else if ( config . key != null && config . cert != null ) {
141+ if ( Array . isArray ( config . key ) && Array . isArray ( config . cert ) ) {
142+ if ( config . key . length !== config . cert . length ) {
143+ throw new errors . ErrorQUICConfig ( 'The number of keys must match the number of certs' ) ;
144+ }
145+ }
146+ }
147+ // This is a concatenated CA certificates in PEM format
141148 let caPEMBuffer : Uint8Array | undefined ;
142149 if ( config . ca != null ) {
143150 let caPEMString = '' ;
@@ -156,48 +163,51 @@ function buildQuicheConfig(config: QUICConfig): QuicheConfig {
156163 }
157164 caPEMBuffer = textEncoder . encode ( caPEMString ) ;
158165 }
159-
160- // Setup: [keyPEM, keyPEM, keyPEM]
161- // AND [certChainPem, certChainPEM, certChainPEM]
162- // Then we pass it in
163- // atm, i don't think this actually works
164- // due to lack of this `SSL_CTX_add1_chain_cert` function
165-
166-
167-
168-
169- // let certChainPem: Buffer | null = null;
170- // let privKeyPem: Buffer | null = null;
171- // if (config.tlsConfig != null && 'certChainPem' in config.tlsConfig) {
172- // if (config.tlsConfig.certChainPem != null) {
173- // certChainPem = Buffer.from(config.tlsConfig.certChainPem);
174- // }
175- // if (config.tlsConfig.privKeyPem != null) {
176- // privKeyPem = Buffer.from(config.tlsConfig.privKeyPem);
177- // }
178- // }
179-
180-
181- const quicheConfig : QuicheConfig = quiche . Config . withBoringSslCtx (
182- certChainPem ,
183- privKeyPem ,
184- config . supportedPrivateKeyAlgos ?? null ,
185- caBuffer ,
186- config . verifyPeer ,
187- ) ;
188- if ( config . tlsConfig != null && 'certChainFromPemFile' in config . tlsConfig ) {
189- if ( config . tlsConfig ?. certChainFromPemFile != null ) {
190- quicheConfig . loadCertChainFromPemFile (
191- config . tlsConfig . certChainFromPemFile ,
192- ) ;
166+ // This is an array of private keys in PEM format
167+ let keyPEMBuffers : Array < Uint8Array > | undefined ;
168+ if ( config . key != null ) {
169+ let keyPEMs : Array < string > = [ ] ;
170+ if ( typeof config . key === 'string' ) {
171+ keyPEMs . push ( config . key . trim ( ) + '\n' ) ;
172+ } else if ( config . key instanceof Uint8Array ) {
173+ keyPEMs . push ( textDecoder . decode ( config . key ) . trim ( ) + '\n' ) ;
174+ } else if ( Array . isArray ( config . key ) ) {
175+ for ( const k of config . key ) {
176+ if ( typeof k === 'string' ) {
177+ keyPEMs . push ( k . trim ( ) + '\n' ) ;
178+ } else {
179+ keyPEMs . push ( textDecoder . decode ( k ) . trim ( ) + '\n' ) ;
180+ }
181+ }
193182 }
194- if ( config . tlsConfig ?. privKeyFromPemFile != null ) {
195- quicheConfig . loadPrivKeyFromPemFile ( config . tlsConfig . privKeyFromPemFile ) ;
183+ keyPEMBuffers = keyPEMs . map ( ( k ) => textEncoder . encode ( k ) ) ;
184+ }
185+ // This is an array of certificate chains in PEM format
186+ let certChainPEMBuffers : Array < Uint8Array > | undefined ;
187+ if ( config . cert != null ) {
188+ let certChainPEMs : Array < string > = [ ] ;
189+ if ( typeof config . cert === 'string' ) {
190+ certChainPEMs . push ( config . cert . trim ( ) + '\n' ) ;
191+ } else if ( config . cert instanceof Uint8Array ) {
192+ certChainPEMs . push ( textDecoder . decode ( config . cert ) . trim ( ) + '\n' ) ;
193+ } else if ( Array . isArray ( config . cert ) ) {
194+ for ( const c of config . cert ) {
195+ if ( typeof c === 'string' ) {
196+ certChainPEMs . push ( c . trim ( ) + '\n' ) ;
197+ } else {
198+ certChainPEMs . push ( textDecoder . decode ( c ) . trim ( ) + '\n' ) ;
199+ }
200+ }
196201 }
202+ certChainPEMBuffers = certChainPEMs . map ( ( c ) => textEncoder . encode ( c ) ) ;
197203 }
198- // if (config.verifyFromPemFile != null) {
199- // quicheConfig.loadVerifyLocationsFromFile(config.verifyFromPemFile);
200- // }
204+ const quicheConfig : QuicheConfig = quiche . Config . withBoringSslCtx (
205+ config . verifyPeer ,
206+ caPEMBuffer ,
207+ keyPEMBuffers ,
208+ certChainPEMBuffers ,
209+ config . sigalgs ,
210+ ) ;
201211 if ( config . logKeys != null ) {
202212 quicheConfig . logKeys ( ) ;
203213 }
0 commit comments