@ -220,16 +220,26 @@ void DH_Server::build(SSL& ssl)
// read PreMaster secret and decrypt, server side
// read PreMaster secret and decrypt, server side
void EncryptedPreMasterSecret : : read ( SSL & ssl , input_buffer & input )
void EncryptedPreMasterSecret : : read ( SSL & ssl , input_buffer & input )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
const CertManager & cert = ssl . getCrypto ( ) . get_certManager ( ) ;
const CertManager & cert = ssl . getCrypto ( ) . get_certManager ( ) ;
RSA rsa ( cert . get_privateKey ( ) , cert . get_privateKeyLength ( ) , false ) ;
RSA rsa ( cert . get_privateKey ( ) , cert . get_privateKeyLength ( ) , false ) ;
uint16 cipherLen = rsa . get_cipherLength ( ) ;
uint16 cipherLen = rsa . get_cipherLength ( ) ;
if ( ssl . isTLS ( ) ) {
if ( ssl . isTLS ( ) ) {
byte len [ 2 ] ;
byte len [ 2 ] ;
input . read ( len , sizeof ( len ) ) ;
len [ 0 ] = input [ AUTO ] ;
len [ 1 ] = input [ AUTO ] ;
ato16 ( len , cipherLen ) ;
ato16 ( len , cipherLen ) ;
}
}
alloc ( cipherLen ) ;
alloc ( cipherLen ) ;
input . read ( secret_ , length_ ) ;
input . read ( secret_ , length_ ) ;
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
opaque preMasterSecret [ SECRET_LEN ] ;
opaque preMasterSecret [ SECRET_LEN ] ;
rsa . decrypt ( preMasterSecret , secret_ , length_ ,
rsa . decrypt ( preMasterSecret , secret_ , length_ ,
@ -277,6 +287,11 @@ void EncryptedPreMasterSecret::alloc(int sz)
// read client's public key, server side
// read client's public key, server side
void ClientDiffieHellmanPublic : : read ( SSL & ssl , input_buffer & input )
void ClientDiffieHellmanPublic : : read ( SSL & ssl , input_buffer & input )
{
{
if ( input . get_error ( ) | | input . get_remaining ( ) < ( uint ) LENGTH_SZ ) {
ssl . SetError ( bad_input ) ;
return ;
}
DiffieHellman & dh = ssl . useCrypto ( ) . use_dh ( ) ;
DiffieHellman & dh = ssl . useCrypto ( ) . use_dh ( ) ;
uint16 keyLength ;
uint16 keyLength ;
@ -287,6 +302,10 @@ void ClientDiffieHellmanPublic::read(SSL& ssl, input_buffer& input)
alloc ( keyLength ) ;
alloc ( keyLength ) ;
input . read ( Yc_ , keyLength ) ;
input . read ( Yc_ , keyLength ) ;
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
dh . makeAgreement ( Yc_ , keyLength ) ;
dh . makeAgreement ( Yc_ , keyLength ) ;
// because of encoding, first byte might be 0, don't use for preMaster
// because of encoding, first byte might be 0, don't use for preMaster
@ -331,6 +350,10 @@ void ClientDiffieHellmanPublic::alloc(int sz, bool offset)
// read server's p, g, public key and sig, client side
// read server's p, g, public key and sig, client side
void DH_Server : : read ( SSL & ssl , input_buffer & input )
void DH_Server : : read ( SSL & ssl , input_buffer & input )
{
{
if ( input . get_error ( ) | | input . get_remaining ( ) < ( uint ) LENGTH_SZ ) {
ssl . SetError ( bad_input ) ;
return ;
}
uint16 length , messageTotal = 6 ; // pSz + gSz + pubSz
uint16 length , messageTotal = 6 ; // pSz + gSz + pubSz
byte tmp [ 2 ] ;
byte tmp [ 2 ] ;
@ -341,6 +364,10 @@ void DH_Server::read(SSL& ssl, input_buffer& input)
messageTotal + = length ;
messageTotal + = length ;
input . read ( parms_ . alloc_p ( length ) , length ) ;
input . read ( parms_ . alloc_p ( length ) , length ) ;
if ( input . get_error ( ) | | input . get_remaining ( ) < ( uint ) LENGTH_SZ ) {
ssl . SetError ( bad_input ) ;
return ;
}
// g
// g
tmp [ 0 ] = input [ AUTO ] ;
tmp [ 0 ] = input [ AUTO ] ;
@ -349,6 +376,10 @@ void DH_Server::read(SSL& ssl, input_buffer& input)
messageTotal + = length ;
messageTotal + = length ;
input . read ( parms_ . alloc_g ( length ) , length ) ;
input . read ( parms_ . alloc_g ( length ) , length ) ;
if ( input . get_error ( ) | | input . get_remaining ( ) < ( uint ) LENGTH_SZ ) {
ssl . SetError ( bad_input ) ;
return ;
}
// pub
// pub
tmp [ 0 ] = input [ AUTO ] ;
tmp [ 0 ] = input [ AUTO ] ;
@ -357,12 +388,20 @@ void DH_Server::read(SSL& ssl, input_buffer& input)
messageTotal + = length ;
messageTotal + = length ;
input . read ( parms_ . alloc_pub ( length ) , length ) ;
input . read ( parms_ . alloc_pub ( length ) , length ) ;
if ( input . get_error ( ) | | input . get_remaining ( ) < ( uint ) LENGTH_SZ ) {
ssl . SetError ( bad_input ) ;
return ;
}
// save message for hash verify
// save message for hash verify
input_buffer message ( messageTotal ) ;
input_buffer message ( messageTotal ) ;
input . set_current ( input . get_current ( ) - messageTotal ) ;
input . set_current ( input . get_current ( ) - messageTotal ) ;
input . read ( message . get_buffer ( ) , messageTotal ) ;
input . read ( message . get_buffer ( ) , messageTotal ) ;
message . add_size ( messageTotal ) ;
message . add_size ( messageTotal ) ;
if ( input . get_error ( ) | | input . get_remaining ( ) < ( uint ) LENGTH_SZ ) {
ssl . SetError ( bad_input ) ;
return ;
}
// signature
// signature
tmp [ 0 ] = input [ AUTO ] ;
tmp [ 0 ] = input [ AUTO ] ;
@ -371,6 +410,10 @@ void DH_Server::read(SSL& ssl, input_buffer& input)
signature_ = NEW_YS byte [ length ] ;
signature_ = NEW_YS byte [ length ] ;
input . read ( signature_ , length ) ;
input . read ( signature_ , length ) ;
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
// verify signature
// verify signature
byte hash [ FINISHED_SZ ] ;
byte hash [ FINISHED_SZ ] ;
@ -645,6 +688,10 @@ void HandShakeHeader::Process(input_buffer& input, SSL& ssl)
{
{
ssl . verifyState ( * this ) ;
ssl . verifyState ( * this ) ;
if ( ssl . GetError ( ) ) return ;
if ( ssl . GetError ( ) ) return ;
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
const HandShakeFactory & hsf = ssl . getFactory ( ) . getHandShake ( ) ;
const HandShakeFactory & hsf = ssl . getFactory ( ) . getHandShake ( ) ;
mySTL : : auto_ptr < HandShakeBase > hs ( hsf . CreateObject ( type_ ) ) ;
mySTL : : auto_ptr < HandShakeBase > hs ( hsf . CreateObject ( type_ ) ) ;
if ( ! hs . get ( ) ) {
if ( ! hs . get ( ) ) {
@ -810,8 +857,13 @@ uint16 ChangeCipherSpec::get_length() const
// CipherSpec processing handler
// CipherSpec processing handler
void ChangeCipherSpec : : Process ( input_buffer & , SSL & ssl )
void ChangeCipherSpec : : Process ( input_buffer & input , SSL & ssl )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
ssl . useSecurity ( ) . use_parms ( ) . pending_ = false ;
ssl . useSecurity ( ) . use_parms ( ) . pending_ = false ;
if ( ssl . getSecurity ( ) . get_resuming ( ) ) {
if ( ssl . getSecurity ( ) . get_resuming ( ) ) {
if ( ssl . getSecurity ( ) . get_parms ( ) . entity_ = = client_end )
if ( ssl . getSecurity ( ) . get_parms ( ) . entity_ = = client_end )
@ -873,6 +925,11 @@ output_buffer& operator<<(output_buffer& output, const Alert& a)
// Alert processing handler
// Alert processing handler
void Alert : : Process ( input_buffer & input , SSL & ssl )
void Alert : : Process ( input_buffer & input , SSL & ssl )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
if ( ssl . getSecurity ( ) . get_parms ( ) . pending_ = = false ) { // encrypted alert
if ( ssl . getSecurity ( ) . get_parms ( ) . pending_ = = false ) { // encrypted alert
int aSz = get_length ( ) ; // alert size already read on input
int aSz = get_length ( ) ; // alert size already read on input
opaque verify [ SHA_LEN ] ;
opaque verify [ SHA_LEN ] ;
@ -890,12 +947,19 @@ void Alert::Process(input_buffer& input, SSL& ssl)
if ( ssl . getSecurity ( ) . get_parms ( ) . cipher_type_ = = block ) {
if ( ssl . getSecurity ( ) . get_parms ( ) . cipher_type_ = = block ) {
int ivExtra = 0 ;
int ivExtra = 0 ;
opaque fill ;
if ( ssl . isTLSv1_1 ( ) )
if ( ssl . isTLSv1_1 ( ) )
ivExtra = ssl . getCrypto ( ) . get_cipher ( ) . get_blockSize ( ) ;
ivExtra = ssl . getCrypto ( ) . get_cipher ( ) . get_blockSize ( ) ;
int padSz = ssl . getSecurity ( ) . get_parms ( ) . encrypt_size_ - ivExtra -
int padSz = ssl . getSecurity ( ) . get_parms ( ) . encrypt_size_ - ivExtra -
aSz - digestSz ;
aSz - digestSz ;
input . set_current ( input . get_current ( ) + padSz ) ;
for ( int i = 0 ; i < padSz ; i + + )
fill = input [ AUTO ] ;
}
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
}
// verify
// verify
@ -1112,6 +1176,11 @@ static int timing_verify(SSL& ssl, const byte* input, int padLen, int t,
// Process handler for Data
// Process handler for Data
void Data : : Process ( input_buffer & input , SSL & ssl )
void Data : : Process ( input_buffer & input , SSL & ssl )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
int msgSz = ssl . getSecurity ( ) . get_parms ( ) . encrypt_size_ ;
int msgSz = ssl . getSecurity ( ) . get_parms ( ) . encrypt_size_ ;
int pad = 0 , padSz = 0 ;
int pad = 0 , padSz = 0 ;
int ivExtra = 0 ;
int ivExtra = 0 ;
@ -1154,7 +1223,7 @@ void Data::Process(input_buffer& input, SSL& ssl)
int dataSz = msgSz - ivExtra - digestSz - pad - padSz ;
int dataSz = msgSz - ivExtra - digestSz - pad - padSz ;
if ( dataSz < 0 ) {
if ( dataSz < 0 | | dataSz > ( MAX_RECORD_SIZE + COMPRESS_EXTRA ) ) {
ssl . SetError ( bad_input ) ;
ssl . SetError ( bad_input ) ;
return ;
return ;
}
}
@ -1180,6 +1249,10 @@ void Data::Process(input_buffer& input, SSL& ssl)
// advance past mac and fill
// advance past mac and fill
input . set_current ( input . get_current ( ) + digestSz + pad + padSz ) ;
input . set_current ( input . get_current ( ) + digestSz + pad + padSz ) ;
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
}
}
@ -1244,6 +1317,11 @@ output_buffer& operator<<(output_buffer& output, const Certificate& cert)
// certificate processing handler
// certificate processing handler
void Certificate : : Process ( input_buffer & input , SSL & ssl )
void Certificate : : Process ( input_buffer & input , SSL & ssl )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
CertManager & cm = ssl . useCrypto ( ) . use_certManager ( ) ;
CertManager & cm = ssl . useCrypto ( ) . use_certManager ( ) ;
uint32 list_sz ;
uint32 list_sz ;
@ -1412,6 +1490,10 @@ input_buffer& operator>>(input_buffer& input, ServerHello& hello)
// Session
// Session
hello . id_len_ = input [ AUTO ] ;
hello . id_len_ = input [ AUTO ] ;
if ( hello . id_len_ > ID_LEN ) {
input . set_error ( ) ;
return input ;
}
if ( hello . id_len_ )
if ( hello . id_len_ )
input . read ( hello . session_id_ , hello . id_len_ ) ;
input . read ( hello . session_id_ , hello . id_len_ ) ;
@ -1452,8 +1534,13 @@ output_buffer& operator<<(output_buffer& output, const ServerHello& hello)
// Server Hello processing handler
// Server Hello processing handler
void ServerHello : : Process ( input_buffer & , SSL & ssl )
void ServerHello : : Process ( input_buffer & input , SSL & ssl )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
if ( ssl . GetMultiProtocol ( ) ) { // SSLv23 support
if ( ssl . GetMultiProtocol ( ) ) { // SSLv23 support
if ( ssl . isTLS ( ) & & server_version_ . minor_ < 1 )
if ( ssl . isTLS ( ) & & server_version_ . minor_ < 1 )
// downgrade to SSLv3
// downgrade to SSLv3
@ -1547,8 +1634,12 @@ const opaque* ServerHello::get_random() const
// Server Hello Done processing handler
// Server Hello Done processing handler
void ServerHelloDone : : Process ( input_buffer & , SSL & ssl )
void ServerHelloDone : : Process ( input_buffer & input , SSL & ssl )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
ssl . useStates ( ) . useClient ( ) = serverHelloDoneComplete ;
ssl . useStates ( ) . useClient ( ) = serverHelloDoneComplete ;
}
}
@ -1667,8 +1758,13 @@ output_buffer& operator<<(output_buffer& output, const ClientHello& hello)
// Client Hello processing handler
// Client Hello processing handler
void ClientHello : : Process ( input_buffer & , SSL & ssl )
void ClientHello : : Process ( input_buffer & input , SSL & ssl )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
// store version for pre master secret
// store version for pre master secret
ssl . useSecurity ( ) . use_connection ( ) . chVersion_ = client_version_ ;
ssl . useSecurity ( ) . use_connection ( ) . chVersion_ = client_version_ ;
@ -1800,9 +1896,17 @@ output_buffer& operator<<(output_buffer& output, const ServerKeyExchange& sk)
// Server Key Exchange processing handler
// Server Key Exchange processing handler
void ServerKeyExchange : : Process ( input_buffer & input , SSL & ssl )
void ServerKeyExchange : : Process ( input_buffer & input , SSL & ssl )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
createKey ( ssl ) ;
createKey ( ssl ) ;
if ( ssl . GetError ( ) ) return ;
if ( ssl . GetError ( ) ) return ;
server_key_ - > read ( ssl , input ) ;
server_key_ - > read ( ssl , input ) ;
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
ssl . useStates ( ) . useClient ( ) = serverKeyExchangeComplete ;
ssl . useStates ( ) . useClient ( ) = serverKeyExchangeComplete ;
}
}
@ -1924,18 +2028,24 @@ input_buffer& operator>>(input_buffer& input, CertificateRequest& request)
{
{
// types
// types
request . typeTotal_ = input [ AUTO ] ;
request . typeTotal_ = input [ AUTO ] ;
if ( request . typeTotal_ > CERT_TYPES ) {
input . set_error ( ) ;
return input ;
}
for ( int i = 0 ; i < request . typeTotal_ ; i + + )
for ( int i = 0 ; i < request . typeTotal_ ; i + + )
request . certificate_types_ [ i ] = ClientCertificateType ( input [ AUTO ] ) ;
request . certificate_types_ [ i ] = ClientCertificateType ( input [ AUTO ] ) ;
byte tmp [ REQUEST_HEADER ] ;
input . read ( tmp , sizeof ( tmp ) ) ;
byte tmp [ 2 ] ;
tmp [ 0 ] = input [ AUTO ] ;
tmp [ 1 ] = input [ AUTO ] ;
uint16 sz ;
uint16 sz ;
ato16 ( tmp , sz ) ;
ato16 ( tmp , sz ) ;
// authorities
// authorities
while ( sz ) {
while ( sz ) {
uint16 dnSz ;
uint16 dnSz ;
input . read ( tmp , sizeof ( tmp ) ) ;
tmp [ 0 ] = input [ AUTO ] ;
tmp [ 1 ] = input [ AUTO ] ;
ato16 ( tmp , dnSz ) ;
ato16 ( tmp , dnSz ) ;
DistinguishedName dn ;
DistinguishedName dn ;
@ -1945,6 +2055,9 @@ input_buffer& operator>>(input_buffer& input, CertificateRequest& request)
input . read ( & dn [ REQUEST_HEADER ] , dnSz ) ;
input . read ( & dn [ REQUEST_HEADER ] , dnSz ) ;
sz - = dnSz + REQUEST_HEADER ;
sz - = dnSz + REQUEST_HEADER ;
if ( input . get_error ( ) )
break ;
}
}
return input ;
return input ;
@ -1983,8 +2096,12 @@ output_buffer& operator<<(output_buffer& output,
// CertificateRequest processing handler
// CertificateRequest processing handler
void CertificateRequest : : Process ( input_buffer & , SSL & ssl )
void CertificateRequest : : Process ( input_buffer & input , SSL & ssl )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
CertManager & cm = ssl . useCrypto ( ) . use_certManager ( ) ;
CertManager & cm = ssl . useCrypto ( ) . use_certManager ( ) ;
cm . setSendVerify ( ) ;
cm . setSendVerify ( ) ;
@ -2067,7 +2184,8 @@ output_buffer& CertificateVerify::get(output_buffer& out) const
input_buffer & operator > > ( input_buffer & input , CertificateVerify & request )
input_buffer & operator > > ( input_buffer & input , CertificateVerify & request )
{
{
byte tmp [ VERIFY_HEADER ] ;
byte tmp [ VERIFY_HEADER ] ;
input . read ( tmp , sizeof ( tmp ) ) ;
tmp [ 0 ] = input [ AUTO ] ;
tmp [ 1 ] = input [ AUTO ] ;
uint16 sz = 0 ;
uint16 sz = 0 ;
ato16 ( tmp , sz ) ;
ato16 ( tmp , sz ) ;
@ -2091,8 +2209,13 @@ output_buffer& operator<<(output_buffer& output,
// CertificateVerify processing handler
// CertificateVerify processing handler
void CertificateVerify : : Process ( input_buffer & , SSL & ssl )
void CertificateVerify : : Process ( input_buffer & input , SSL & ssl )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
const Hashes & hashVerify = ssl . getHashes ( ) . get_certVerify ( ) ;
const Hashes & hashVerify = ssl . getHashes ( ) . get_certVerify ( ) ;
const CertManager & cert = ssl . getCrypto ( ) . get_certManager ( ) ;
const CertManager & cert = ssl . getCrypto ( ) . get_certManager ( ) ;
@ -2131,9 +2254,17 @@ output_buffer& operator<<(output_buffer& output, const ClientKeyExchange& ck)
// Client Key Exchange processing handler
// Client Key Exchange processing handler
void ClientKeyExchange : : Process ( input_buffer & input , SSL & ssl )
void ClientKeyExchange : : Process ( input_buffer & input , SSL & ssl )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
createKey ( ssl ) ;
createKey ( ssl ) ;
if ( ssl . GetError ( ) ) return ;
if ( ssl . GetError ( ) ) return ;
client_key_ - > read ( ssl , input ) ;
client_key_ - > read ( ssl , input ) ;
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
if ( ssl . getCrypto ( ) . get_certManager ( ) . verifyPeer ( ) )
if ( ssl . getCrypto ( ) . get_certManager ( ) . verifyPeer ( ) )
build_certHashes ( ssl , ssl . useHashes ( ) . use_certVerify ( ) ) ;
build_certHashes ( ssl , ssl . useHashes ( ) . use_certVerify ( ) ) ;
@ -2220,11 +2351,19 @@ output_buffer& operator<<(output_buffer& output, const Finished& fin)
// Finished processing handler
// Finished processing handler
void Finished : : Process ( input_buffer & input , SSL & ssl )
void Finished : : Process ( input_buffer & input , SSL & ssl )
{
{
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
// verify hashes
// verify hashes
const Finished & verify = ssl . getHashes ( ) . get_verify ( ) ;
const Finished & verify = ssl . getHashes ( ) . get_verify ( ) ;
uint finishedSz = ssl . isTLS ( ) ? TLS_FINISHED_SZ : FINISHED_SZ ;
uint finishedSz = ssl . isTLS ( ) ? TLS_FINISHED_SZ : FINISHED_SZ ;
input . read ( hashes_ . md5_ , finishedSz ) ;
input . read ( hashes_ . md5_ , finishedSz ) ;
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
if ( memcmp ( & hashes_ , & verify . hashes_ , finishedSz ) ) {
if ( memcmp ( & hashes_ , & verify . hashes_ , finishedSz ) ) {
ssl . SetError ( verify_error ) ;
ssl . SetError ( verify_error ) ;
@ -2246,19 +2385,23 @@ void Finished::Process(input_buffer& input, SSL& ssl)
opaque mac [ SHA_LEN ] ; // max size
opaque mac [ SHA_LEN ] ; // max size
int digestSz = ssl . getCrypto ( ) . get_digest ( ) . get_digestSize ( ) ;
int digestSz = ssl . getCrypto ( ) . get_digest ( ) . get_digestSize ( ) ;
input . read ( mac , digestSz ) ;
input . read ( mac , digestSz ) ;
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
}
uint ivExtra = 0 ;
uint ivExtra = 0 ;
if ( ssl . getSecurity ( ) . get_parms ( ) . cipher_type_ = = block )
if ( ssl . getSecurity ( ) . get_parms ( ) . cipher_type_ = = block )
if ( ssl . isTLSv1_1 ( ) )
if ( ssl . isTLSv1_1 ( ) )
ivExtra = ssl . getCrypto ( ) . get_cipher ( ) . get_blockSize ( ) ;
ivExtra = ssl . getCrypto ( ) . get_cipher ( ) . get_blockSize ( ) ;
opaque fill ;
int padSz = ssl . getSecurity ( ) . get_parms ( ) . encrypt_size_ - ivExtra -
int padSz = ssl . getSecurity ( ) . get_parms ( ) . encrypt_size_ - ivExtra -
HANDSHAKE_HEADER - finishedSz - digestSz ;
HANDSHAKE_HEADER - finishedSz - digestSz ;
input . set_current ( input . get_current ( ) + padSz ) ;
// verify mac
if ( memcmp ( mac , verifyMAC , digestSz ) ) {
ssl . SetError ( verify_error ) ;
for ( int i = 0 ; i < padSz ; i + + )
fill = input [ AUTO ] ;
if ( input . get_error ( ) ) {
ssl . SetError ( bad_input ) ;
return ;
return ;
}
}