Hi there, I need a little CMS wraper. I need decode S/MIME message chunk by chunk. I start make it based on cmsutil. But I receive "segmentation fault" every time on call NSS_CMSDecoder_Update. What's wrong?



//----- wraper code

#include <unistd.h>

#include <stdio.h>
#include <string.h>

#include <vector>
#include <string>

 class SmimeDecoder //: public sigslot::has_slots<>
{
public:

        SmimeDecoder();
        SmimeDecoder(SmimeDecoder& sd);
        ~SmimeDecoder();

        void PutCipherText(void* buffer, const int lenght);

        /*sigslot::signal2<const void*, const int> OnHavePlainText;
        sigslot::signal1<const int> OnDecryptionFailed;*/

        char* PasswordCallback(PK11SlotInfo *slot, PRBool retry, void *arg);
        void* _password_arg;
        //static
        PK11SymKey* KeyCallback(void *arg, SECAlgorithmID *algid);

        void ContentCallback(void *arg, const char *buf, unsigned long len);

        PK11SymKey* GetKey()
        {
                return _bulk_key;
        }

        void* getPassword()
        {
                return _password_arg;
        }

        void* getContentArg()
        {
                return NULL;
        }

private:
        PLArenaPool     *_pool;

        bool _begin_decoding;
        void decode_message_start();

        NSSCMSMessage * decode_message_append(void* buffer, const int lenght);
        PK11SymKey *_bulk_key;

        NSSCMSDecoderContext *_decoder_context;
        NSSCMSMessage *_cms_message;

        CERTCertDBHandle *_cert_db_handle;

};

SmimeDecoder::SmimeDecoder() : _begin_decoding(false), _pool(NULL)
{
        //_key_callback = (NSSCMSGetDecryptKeyCallback)&this->KeyCallback;
        //_key_callback = &SmimeDecoder::KeyCallback;

        //_pool = PORT_NewArena(10240);
}

SmimeDecoder::SmimeDecoder(SmimeDecoder& sd)
{
}
        
SmimeDecoder::~SmimeDecoder()
{
}



PK11SymKey* key_callback_thunk(void* arg, SECAlgorithmID *algid)
{
        SmimeDecoder* sd = reinterpret_cast<SmimeDecoder*>( arg );
        return ( sd->KeyCallback(sd->GetKey(), algid) );
}

PK11SymKey* SmimeDecoder::KeyCallback(void *arg, SECAlgorithmID *algid)
{
        return (PK11SymKey*)arg;
}

char* password_callback_thunk(PK11SlotInfo *slot, PRBool retry, void *arg)
{
        SmimeDecoder* sd = reinterpret_cast<SmimeDecoder*>( arg );
        return ( sd->PasswordCallback(slot, retry, sd->getPassword()) );
}

char* SmimeDecoder::PasswordCallback(PK11SlotInfo *slot, PRBool retry, void *arg)
{
        arg = NULL;

    //PK11_SetPasswordFunc(SECU_GetModulePassword);
    //PK11_SetPasswordFunc(&SECU_GetModulePassword);
        //SECU_GetModulePassword();
}

void content_callback_thunk(void *arg, const char *buf, unsigned long len)
{
        SmimeDecoder* sd = reinterpret_cast<SmimeDecoder*>( arg );
        sd->ContentCallback(sd->getContentArg(), buf, len);
        return;
}

void SmimeDecoder::ContentCallback(void *arg, const char *buf, unsigned long len)
{
        arg = NULL;
}
/*char * ownPasswd( PK11SlotInfo *slot, PRBool retry, void *arg)
{
        char *passwd = NULL;
        if ( (!retry) && arg ) {
                passwd = PL_strdup((char *)arg);
        }
        return passwd;
}*/

void SmimeDecoder::PutCipherText(void* buffer, const int lenght)
{
        NSSCMSMessage *msg = NULL;

        if( !_begin_decoding ){//_begin_decoding == false
                decode_message_start();//buffer, lenght);
                msg = decode_message_append(buffer, lenght);
        } else {//_begin_decoding == true
                msg = decode_message_append(buffer, lenght);
                //if ( isFinal ){
                //}
        }
}

void SmimeDecoder::decode_message_start()//void* buffer, const int lenght)
{
        _begin_decoding = true;

        PORT_SetError(0);
        _decoder_context = NSS_CMSDecoder_Start(_pool,
                                                           //NULL, NULL,
                                                           
content_callback_thunk, this,
        //                                                 PasswordCallback, 
_password_arg,
                                                           
password_callback_thunk, this,
                                                           //KeyCallback,
                                                           key_callback_thunk, 
this);//_bulk_key
        
        if (!_decoder_context) {
                std::cout << "shit happens!" << std::endl;
        }
}

NSSCMSMessage * SmimeDecoder::decode_message_append(void* buffer, const int lenght)
{
        int nlevels;//, i;

        SECItem sitem = { (SECItemType)0, 0, 0 };

    //NSSCMSGetDecryptKeyCallback
        //(void)
        //_decoder_context
        (void)NSS_CMSDecoder_Update(_decoder_context, (char *)buffer, lenght);
        /*if (stat != SECSuccess) {
                std::cout << "shit happens!" << std::endl;
        }*/
        /*if( !isFinal )
                return _cms_message;
        else
                _cms_message = NSS_CMSDecoder_Finish( _decoder_context );
        */

        nlevels = NSS_CMSMessage_ContentLevelCount(_cms_message);
        for (int i = 0; i < nlevels; i++) {
        NSSCMSContentInfo *cinfo;
        SECOidTag typetag;

        cinfo = NSS_CMSMessage_ContentLevel(_cms_message, i);
        typetag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);

        /*if (decodeOptions->headerLevel >= 0)
fprintf(out, "\tlevel=%d.%d; ", decodeOptions->headerLevel, nlevels - i);*/

                switch (typetag) {
                case SEC_OID_PKCS7_SIGNED_DATA:
                  {
                        NSSCMSSignedData *sigd = NULL;
                        SECItem **digests;
                        int nsigners;
                        int j;
        
                        /*if (decodeOptions->headerLevel >= 0)
                        fprintf(out, "type=signedData; ");*/
                        sigd = (NSSCMSSignedData 
*)NSS_CMSContentInfo_GetContent(cinfo);
                        if (sigd == NULL) {
                        //SECU_PrintError(progName, "signedData component 
missing");
                        goto loser;
                        }
        
                        /* if we have a content file, but no digests for this 
signedData */
if (!NSS_CMSSignedData_HasDigests(sigd)) {//decodeOptions->content.data != NULL &&
                        PLArenaPool     *poolp;
                        SECAlgorithmID **digestalgs;
        
                        /* detached content: grab content file */
                        //sitem = decodeOptions->content;
        
                        if ((poolp = PORT_NewArena(1024)) == NULL) {
                                fprintf(stderr, "cmsutil: Out of memory.\n");
                                goto loser;
                        }
                        digestalgs = NSS_CMSSignedData_GetDigestAlgs(sigd);
                        if (1)//DigestFile (poolp, &digests, &sitem, 
digestalgs) != SECSuccess)
                        {
                         /*   SECU_PrintError(progName,
                                                                "problem computing 
message digest");*/
                                PORT_FreeArena(poolp, PR_FALSE);
                                goto loser;
                        }
                        if (NSS_CMSSignedData_SetDigests(sigd, digestalgs, 
digests)
                                != SECSuccess) {
                                /*SECU_PrintError(progName,
                                                                "problem setting 
message digests");*/
                                PORT_FreeArena(poolp, PR_FALSE);
                                goto loser;
                        }
                        PORT_FreeArena(poolp, PR_FALSE);
                        }
        
                        /* import the certificates */
                        /*if (NSS_CMSSignedData_ImportCerts(sigd,
                                                                                   
decodeOptions->options->certHandle,
                                                                                   
decodeOptions->options->certUsage,
                                                                                   
decodeOptions->keepCerts)
                                  != SECSuccess) {
                        SECU_PrintError(progName, "cert import failed");
                        goto loser;
                        }*/
        
                        /* find out about signers */
                        nsigners = NSS_CMSSignedData_SignerInfoCount(sigd);
                        /*if (decodeOptions->headerLevel >= 0)
                        fprintf(out, "nsigners=%d; ", nsigners);*/
                        if (nsigners == 0) {
                        /* Might be a cert transport message
                        ** or might be an invalid message, such as a QA test 
message
                        ** or a message from an attacker.
                        */
                        SECStatus rv;
                        /*rv = NSS_CMSSignedData_VerifyCertsOnly(sigd,
                                                                                
decodeOptions->options->certHandle,
                                                                                
decodeOptions->options->certUsage);*/
                                if (rv != SECSuccess) {
                                        fprintf(stderr, "cmsutil: Verify certs-only 
failed!\n");
                                        goto loser;
                                }
                                return _cms_message;
                        }//cmsg
        
                        /* still no digests? */
                        if (!NSS_CMSSignedData_HasDigests(sigd)) {
                        //SECU_PrintError(progName, "no message digests");
                                goto loser;
                        }
        
                        for (j = 0; j < nsigners; j++) {
                        const char * svs;
                        NSSCMSSignerInfo *si;
                        NSSCMSVerificationStatus vs;
                        SECStatus bad;
        
                        si = NSS_CMSSignedData_GetSignerInfo(sigd, j);
                        if (1) {//decodeOptions->headerLevel >= 0
                                char *signercn;
                                static char empty[] = { "" };
        
                                signercn = 
NSS_CMSSignerInfo_GetSignerCommonName(si);
                                if (signercn == NULL)
                                signercn = empty;
                        //    fprintf(out, "\n\t\tsigner%d.id=\"%s\"; ", j, 
signercn);
                                if (signercn != empty)
                                        PORT_Free(signercn);
                        }
                        /*bad = NSS_CMSSignedData_VerifySignerInfo(sigd, j,
                                                                           
decodeOptions->options->certHandle,
                                                                           
decodeOptions->options->certUsage);*/
                        vs  = NSS_CMSSignerInfo_GetVerificationStatus(si);
                        svs = NSS_CMSUtil_VerificationStatusToString(vs);
                        if (1){//decodeOptions->headerLevel >= 0) {
                                //fprintf(out, "signer%d.status=%s; ", j, svs);
                                /* goto loser ? */
                        } else if (1){//bad && out) {
                                fprintf(stderr, "signer %d status = %s\n", j, 
svs);
                                goto loser;
                        }
                        }
                  }
                  break;
                case SEC_OID_PKCS7_ENVELOPED_DATA:
                  //{
                        NSSCMSEnvelopedData *envd;
                        if (1)//decodeOptions->headerLevel >= 0)
                        //fprintf(out, "type=envelopedData; ");
                        envd = (NSSCMSEnvelopedData 
*)NSS_CMSContentInfo_GetContent(cinfo);
                        if (envd == NULL) {
                        //SECU_PrintError(progName, "envelopedData component 
missing");
                        goto loser;
                        }
                  //}
                  break;
                case SEC_OID_PKCS7_ENCRYPTED_DATA:
                  //{
                        NSSCMSEncryptedData *encd;
                        if (1)//decodeOptions->headerLevel >= 0)
                        //fprintf(out, "type=encryptedData; ");
                        encd = (NSSCMSEncryptedData 
*)NSS_CMSContentInfo_GetContent(cinfo);
                        if (encd == NULL) {
                        //SECU_PrintError(progName, "encryptedData component 
missing");
                        goto loser;
                        }
                  //}
                  break;
                case SEC_OID_PKCS7_DATA:
                        if (1)//decodeOptions->headerLevel >= 0)
                        //fprintf(out, "type=data; ");
                        break;
                default:
                        break;
                }//switch
        //if (1)//decodeOptions->headerLevel >= 0)
                //fprintf(out, "\n");
        }

        /*if (1){//!decodeOptions->suppressContent && out) {
        SECItem *item = (sitem.data ? &sitem
                                                                : 
NSS_CMSMessage_GetContent(cmsg));
        if (item && item->data && item->len) {
                fwrite(item->data, item->len, 1, out);
                }
        }*/
        return _cms_message;

loser:
        if (_cms_message)
        NSS_CMSMessage_Destroy(_cms_message);
        return NULL;
}


static const std::string base64_chars =
             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
             "abcdefghijklmnopqrstuvwxyz"
             "0123456789+/";

static inline bool is_base64(unsigned char c) {
  return (isalnum(c) || (c == '+') || (c == '/'));
}

std::vector<char> base64_decode(std::string const& encoded_string) {
  int in_len = encoded_string.size();
  int i = 0;
  int j = 0;
  int in_ = 0;
  unsigned char char_array_4[4], char_array_3[3];
  std::vector<char> ret;

while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
    char_array_4[i++] = encoded_string[in_]; in_++;
    if (i ==4) {
      for (i = 0; i <4; i++)
        char_array_4[i] = base64_chars.find(char_array_4[i]);

char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
      char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

      for (i = 0; (i < 3); i++)
        ret.push_back(char_array_3[i]);
      i = 0;
    }
  }

  if (i) {
    for (j = i; j <4; j++)
      char_array_4[j] = 0;

    for (j = 0; j <4; j++)
      char_array_4[j] = base64_chars.find(char_array_4[j]);

char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
    char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

    for (j = 0; (j < i - 1); j++) ret.push_back(char_array_3[j]);
  }

  return ret;
}

int main(int argc, char **argv)
{
//Base64 encoded CMS message

std::string s =

std::string("MIAGCSqGSIb3DQEHAqCAMIACAQExADCABgkqhkiG9w0BBwGggCSAAAAAAAAA")
+std::string("oIIHCDCCAlIwggG7oAMCAQICASgwDQYJKoZIhvcNAQEEBQAwZDELMAkGA1UE")
+std::string("BhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWlu")
+std::string("IFZpZXcxEjAQBgNVBAoTCUJPR1VTIE5TUzEUMBIGA1UEAxMLTlNTIFRlc3Qg")
+std::string("Q0EwHhcNMDYxMTIxMTcxNTQzWhcNMTIwMjIxMTcxNTQzWjB6MQswCQYDVQQG")
+std::string("EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g")
+std::string("VmlldzESMBAGA1UEChMJQk9HVVMgTlNTMRwwGgYJKoZIhvcNAQkBFg1Cb2JA")
+std::string("Ym9ndXMuY29tMQwwCgYDVQQDEwNCb2IwgZ8wDQYJKoZIhvcNAQEBBQADgY0A")
+std::string("MIGJAoGBALYpHxqMyRkJ1Sl3ix3Drh5T/Vm1YQ/DgosHqL65hv64hVR94ISe")
+std::string("HvYxILTOKDljnNvlM/TdcFTUQYEz6n8BH4hGwvJ/lX7W7PWY8kYDz/ZalIQ1")
+std::string("laBLRT1KCb3brJaTBi5u5A3Em8SyrH4GVcGvwNnIrtLMfI3OjxCEdoG8lhq5")
+std::string("AgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAqwn3pLrQhweQwNOrrI9GUWM2B/bs")
+std::string("aAicmF9bqk3Rix2Xm8NJBWnJdjAaqNRB3TK4N2+65G0r3Bn7Thw5rjpoRW9z")
+std::string("bPZwJIVFaB5iwYr1io1drq116YLjg1Zx32tdJUAU96DiOMUfFU3BgZsTlWKM")
+std::string("w7Uka1i2bbG1DgAMLZzn0A4wggJUMIIBvaADAgECAgEyMA0GCSqGSIb3DQEB")
+std::string("BAUAMGQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYD")
+std::string("VQQHEw1Nb3VudGFpbiBWaWV3MRIwEAYDVQQKEwlCT0dVUyBOU1MxFDASBgNV")
+std::string("BAMTC05TUyBUZXN0IENBMB4XDTA2MTEyMTE3MTU0OFoXDTEyMDIyMTE3MTU0")
+std::string("OFowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNV")
+std::string("BAcTDU1vdW50YWluIFZpZXcxEjAQBgNVBAoTCUJPR1VTIE5TUzEdMBsGCSqG")
+std::string("SIb3DQEJARYORGF2ZUBib2d1cy5jb20xDTALBgNVBAMTBERhdmUwgZ8wDQYJ")
+std::string("KoZIhvcNAQEBBQADgY0AMIGJAoGBALrL1fn7MxUpq50Z70d3sEwGUeZK1I5H")
+std::string("2KEsGteIz+DsbqFgwY1xU9sskl91T83qHkvTE6DYUA+HGBvXDtzK0VxJYxZN")
+std::string("hSv550gr/G/F3HqI2Dr8KU3KH0k7Sqhw33hH3czznLXkZbFHv10XDVSAlrie")
+std::string("h2Ywe+K2m2nEDx+ChOgTAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAd8BEFq9F")
+std::string("EcYy3eFTwHpQYCZLoRT5/khLLgvX0GuK6fo28Mi3mFZqehW9Fazym2hF3H3m")
+std::string("O1he2U0j8L9j5yE66fEgPuq3dsO6IsmHGt98uucUAfiG+b/Wjw1YJQ+77ae+")
+std::string("+fwCOUHLKaPVSKJvqIP55LBaEMUwifaCmBq5lHtsWjkwggJWMIIBv6ADAgEC")
+std::string("AgEeMA0GCSqGSIb3DQEBBAUAMGQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpD")
+std::string("YWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRIwEAYDVQQKEwlC")
+std::string("T0dVUyBOU1MxFDASBgNVBAMTC05TUyBUZXN0IENBMB4XDTA2MTEyMTE3MTU0")
+std::string("MVoXDTEyMDIyMTE3MTU0MVowfjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNh")
+std::string("bGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxEjAQBgNVBAoTCUJP")
+std::string("R1VTIE5TUzEeMBwGCSqGSIb3DQEJARYPQWxpY2VAYm9ndXMuY29tMQ4wDAYD")
+std::string("VQQDEwVBbGljZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvR03fZov")
+std::string("RBwWvCvggwTF81wKcEeKYr24XBJbsJd5H1jOa+U8790gefGEJhk6iq0OIiUV")
+std::string("XIBjy1ywBlBAJ5BFtx6a1USjTVjIV79JJhCRAZ+9P+OH7EMrlZeVY8Zviu8L")
+std::string("7yRGEy37U6Fyeh+JxqCV8r43r0tR6801scS114rvuWUCAwEAATANBgkqhkiG")
+std::string("9w0BAQQFAAOBgQAlg7eydO8uGxgF0wVqYwv1bhUmD35+TuSQ9yNL9MP0i1VE")
+std::string("+QxnMHXWN6XL7IExOQl/uLN2AO/H6r8RDA7u4/DgyW8PHqL3ywZs3Hsfvamf")
+std::string("3TvO/TKzJlCr478p/4Jbi7lLNpKYMfmT5+JFx+KBFA7Qp6wcHTxFtgcsR8LQ")
+std::string("HIJlxDEAAAAAAAAA")
+std::string("====");

        std::vector<char> str = base64_decode(s);

        int len = str.size();
        char *buffer = new char[len];

        for (int i = 0; i < len; i++) {
                *(buffer + i) = str[i];
        }

        smime::SmimeDecoder *dec = NULL;

        dec = new smime::SmimeDecoder();

        dec->PutCipherText(buffer, len);

        delete dec;
        delete buffer;

        return 0;
}
_______________________________________________
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto

Reply via email to