cancel
Showing results for 
Search instead for 
Did you mean: 

Problems with sapeculib and SsfDecode/SsfVerify

Former Member
0 Kudos

Hi,

(I'm not shure if this is the correct forum, please send me a note if I'm wrong here.)

I try to implement a HTTP Content Server for SAP ArchiveLink, but I have troubles with the url signature. I try to use the sapsecu.dll to verify the PKCS#7 signature, but I fail even with the provided example from SAP.

This is my test code to decode the signature (originally passed via base64) but I always receive the errorcode 12, meaning "wrong format".


// SapSecuWrapper.h
#include <string.h>
#include "AMMimeUtils.h"
#include "ssfxxapi.h"
#pragma once
 
using namespace System;
 
namespace SapSecuWrapper {
 
	public ref class SapSecuWrapper
	{
	public:
 
		static int test(void)
		{
			int b;
 
			char* base64 = "MIIBlgYJKoZIhvcNAQcCoIIBhzCCAYMCAQExCzAJBgUrDgMCGgU
AMAsGCSqGSIb3DQEHATGCAWIwggFeAgEBMBMwDjEMMAoGA1UEAxM
DSUQzAgEAMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZ
IhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wMDA1MDUxNDA2NTFaMCM
GCSqGSIb3DQEJBDEWBBQGYof+huv7Gw7r+UmGzIai+1i3DTCBpwY
FKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61
TX5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhU
BSe/QF4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8p
S22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q
12PFp/PjOhh+nBDAwLgIVAJw5q7oYYDAKplAXqFjOuLTC53daAhU
A1GTCFCLfwwgJWul7yfVYfwc84jk=";
 
			secKeyStr;
			CBase64Utils* cqp = new CBase64Utils();
 
			char* secKeyStr = cqp->Decode(base64, &b);
			SsfOctetstring* a = new SsfOctetstring;
			
			int len = strlen(secKeyStr);
			int r = SsfDecode("PKCS7", 5, secKeyStr, len, a, &b);
 
			delete secKeyStr;
			delete a;
			return r;
		}
 
	};
}

Originally I used a .NET code, but to rule out marshalling problems I moved to C++. I first tried the .NET 2.0 functions but I faced problems there as well.

Can anyone help me, or tell my that I'm on the wrong way?

Thank you in advance,

Christoph

Accepted Solutions (0)

Answers (4)

Answers (4)

Former Member
0 Kudos

Ok. So it works now. The code posted is quite good, the problem was the RSCMSTI function module in the SAP environment which contains a bug! And since we where testing with this method we got stuck...

Former Member
0 Kudos

Hi I used the above code in asp.net with c# and created the wrapper in vc++ 2010 with name(SapSecUWrapper.dll). Its running in my development environment(Win 7 32 bit) but when I am deploying on server which is Window server 2003 32 Bit, I am getting error stating " Could not load file or assembly "SapSecUWrapper.dll " or one of its dependencies. The specified module could not be found."

I used dependency walker to check whether i am missing any dll. But it doesn't help it out.

Please please help me.

Former Member
0 Kudos

Hi Christoph,

I have a few questions about your implementation of HTTP Content Server for SAP ArchiveLink, you can reply here or contact by mail (see profile). thx

Former Member
0 Kudos

Hello,

I'm trying to implement this functionality but keep getting error 5 and 27 as signerresult->uResult.

I've created the C++ library and C# classes in Visual Studio 2005. Please contact me or leave a reply since I'm desperately looking for a solution.

Thanks a lot!

Kind regards,

Guus Creuwels.

Former Member
0 Kudos

<b>C++ class</b>


// SapSecuWrapper.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <time.h>
#include "ssfxxapi.h"
#pragma once

using namespace System;

namespace ADOS {

	public ref class SapSecuWrapper
	{
	public:

		static int CreateProfile(char* psename, char* psepwd) {
			return SsfCreateProfile((SsfCharstring)psename, strlen(psename), psepwd, strlen(psepwd), NULL, 0);
		}

		static int RemoveProfile(char* psename) {
			return SsfRemoveProfile((SsfCharstring)psename, strlen(psename));
		}
		static int putCert(char* psename, char* psepwd, char* _putcert, int _putcert_len)
		{
			SsfOctetstring 		putcert = _putcert;
			SsfOctetlen			putcert_len = _putcert_len;
			SsfOctetstring 		encoded_original_message;
			SsfOctetlen			encoded_original_message_length;
			SsfOctetstring 		ostroutputdata;
			SsfOctetlen			ostroutputdata_len;

			SigRcpSsfInformationList	signerresultlist=NULL;
			PtrSigRcpSsfInformation		signerresult;

			SsfProfileHandle	Profile;
			SsfCertHandle		Certificate;
			SsfOctetstring 		asn1cert;
			SsfOctetlen			asn1certL;

			int rc=0;
			int result2=0;

			/* SsfEncode the original_message (length 1, contents space). */
			rc=SsfEncode("PKCS7",5, " ", 1,
				&encoded_original_message, &encoded_original_message_length);

			if (rc != 0) return rc;
			
			/* SsfVerify the putcert with encoded_original_message */
			rc=SsfVerify("PKCS7",5,
					TRUE,
					putcert, putcert_len,
					encoded_original_message, encoded_original_message_length,
					psename, strlen(psename),
					psepwd,strlen(psepwd),
					&signerresultlist,
					&ostroutputdata,&ostroutputdata_len);

			if (rc != 0 && rc != 5) return rc;
			signerresult = signerresultlist->ptrSigRcp;
			result2= signerresult->uResult;
			if (result2 != SSF_API_SIGNER_OK && result2 != SSF_API_UNKNOWN_RECIPIENT) return -3;

			/* extract certificate */
			asn1cert=signerresult->strSigRcpPassword;
			asn1certL=signerresult->strSigRcpPasswordL;

			/*** Add certificate  to the PAB  ***/
			rc = SsfCertfromASN1(asn1cert,asn1certL,&Certificate);
			if (rc != 0) return rc;
			

			/* open profile */
			rc=SsfOpenProfile(
				psename,strlen(psename),
				psepwd,strlen(psepwd),
				NULL,0,
				&Profile);
			if (rc != 0) return rc;

			rc=SsfPutCertificate(Profile,Certificate);
			if (rc != 0) return rc;	// TODO clean up
			SsfFreeCertificate(&Certificate);

			/* clean up ... 							*/
			SsfDELSsfOctetstring(&encoded_original_message,&encoded_original_message_length);
			SsfDELSsfOctetstring(&ostroutputdata,&ostroutputdata_len);
			SsfDELSigRcpSsfInfoList(&signerresultlist);
			rc=SsfCloseProfile(&Profile);

			return 0;
		}



		
		static int checkUrl(char* psename, char* psepwd, char* _signeduri, int _signeduri_len, char* _signature, int _signature_len)
		{
			SsfOctetstring 		signeduri			= _signeduri;
			SsfOctetlen			signeduri_len		= _signeduri_len;
			SsfOctetstring 		signature			= _signature;
			SsfOctetlen			signature_length	= _signature_len;

			SsfOctetstring 		encoded_signeduri;
			SsfOctetlen			encoded_signeduri_len;
			SsfOctetstring 		result_signeduri;
			SsfOctetlen			result_signeduri_len;

			SigRcpSsfInformationList	signerresultlist=NULL;
			PtrSigRcpSsfInformation		signerresult;

			int rc=0;
			int result2=0;

			/* load signed URI */
			//signeduri_len = read_file("D:\Develop\Ados\SECURITY DOCU\data\httpcsreq_uri.txt", "rt", &signeduri);
			//assert (signeduri_len != 0);
			//if (signeduri_len == 0) return -999;

			/* load signature  */
			//signature_length = read_file("D:\Develop\Ados\SECURITY DOCU\data\httpcsreq_signature.bin", "rb", &signature);
			//assert (signature_length != 0);
			//if (signature_length == 0) return -9999;

			/* SsfEncode the signed URI. */
			//printf("Verifying signature...n");
			rc=SsfEncode("PKCS7",5, signeduri, signeduri_len,
				&encoded_signeduri, &encoded_signeduri_len);
			//assert(rc==0);
			if (rc != 0) return rc;

			/* SsfVerify the putcert with encoded_original_message */
			rc=SsfVerify("PKCS7",5,
					FALSE,
					signature, signature_length,
					encoded_signeduri, encoded_signeduri_len,
					psename, strlen(psename),
					psepwd, strlen(psepwd),
					&signerresultlist,
					&result_signeduri,&result_signeduri_len);

			//assert(signerresultlist != NULL);
			if (signerresultlist == NULL) return -8;
			signerresult = signerresultlist->ptrSigRcp;
			//assert(signerresult != NULL);
			if (signerresult == 0) return -9;
			result2= signerresult->uResult;

			//printf("SsfVerify returned rc: %d, result: %dn",rc,result2);
			//assert(rc==0);
			if (rc != 0) return rc;

			//printf("Signer is: %.*sn",signerresult->strSigRcpIdL,signerresult->strSigRcpId);
			/* TODO: make sure that signer (in signerresult) is allowed to access resource !!! */

			/* clean up ... */
			SsfDELSsfOctetstring(&encoded_signeduri,&encoded_signeduri_len);
			SsfDELSsfOctetstring(&result_signeduri,&result_signeduri_len);
			SsfDELSigRcpSsfInfoList(&signerresultlist);
			//free(signeduri); signeduri=NULL;
			//free(signature); signature=NULL;


			//printf("Signature successfully verifiedn");
			return 0;
		}







		static int read_file(const char *FileName, const char *mode, char **ppdata)
		{
			FILE    *stream;
			char	*pdata = NULL;
			int		ndata = 0;                          /* total number of bytes read from file         */
			int	   	nlastread;                          /* number of bytes read with last fread call    */


														/* open file in given mode                      */
			if ((stream = fopen(FileName, mode)) == NULL)
				return 0;                               /* file open error                              */


			/* try to find out the initial size */
			if (fseek ( stream, 0, SEEK_END )) {
				fclose(stream);
				return 0;
			}
			ndata = ftell ( stream );
			fseek( stream, 0, SEEK_SET );
			pdata = (char*)malloc(ndata);
			if (pdata == NULL) {
				fclose(stream);
				return 0;
			}

			nlastread = fread(pdata, sizeof(char), ndata, stream);
			if (nlastread != ndata) {
				fclose(stream);
				return 0;
			}

			*ppdata = pdata;

			fclose(stream);                             /* close file                                   */
			return ndata;                               /* return number of bytes read from file        */
		}

		static int write_file(const char *FileName, const char *mode, char *pdata, int ndata)
		{
			FILE    *stream;

			if ((stream = fopen(FileName, mode)) == NULL)
				return -1;

			ndata = fwrite(pdata, sizeof(char), ndata, stream);
			fclose(stream);

			return ndata;
		}
	};
}

regards,

Christoph

Former Member
0 Kudos

Hi I used the above code in asp.net with c# and created the wrapper in vc++ 2010 with name(SapSecUWrapper.dll). Its running in my development environment(Win 7 32 bit) but when I am deploying on server which is Window server 2003 32 Bit, I am getting error stating " Could not load file or assembly "SapSecUWrapper.dll " or one of its dependencies. The specified module could not be found."

I used dependency walker to check whether i am missing any dll. But it doesn't help it out.

Please please help me.

Former Member
0 Kudos

I finally worked it out. For other frustrated users, here's my C#/C++/sapseculib solution:

I used a solution with a C# project und a C++ project. The C++ part is referenced via project reference in the C# code.

Maybe the "unsafe" blocks could be replaced with more secure code, but at least it works - if someone has better ideas, feel free to post.

<b>C# class</b>


using System;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using ADOS;

namespace ADOS {

	class Seculib {

		static void Main() {
			int r;
			Seculib sl = new Seculib();

			sl.Pse = @"D:DevelopAdosSignatureTestados.pse";
			sl.PsePassword = "ados";

			r = sl.SetupProfile();
			Console.WriteLine("Setup Profile " + r);

			byte[] fileBuffer = ReadFile(@"D:DevelopAdosSignatureTestcertificate.cer");
			r = sl.PutCertificate(fileBuffer);
			Console.WriteLine("Put Certificate " + r);

			string uri = "T1EB9074DF46723B49A05CAEAB57DB9B98uCN%3DID320051222141521";
			string signatureBase64 = "MIIBlQYJKoZIhvcNAQcCoIIBhjCCAYICAQExCzAJBgUrDgMCGgUAMAsGCSqGSIb3DQEHATGCAWEwggFdAgEBMBMwDjEMMAoGA1UEAxMDSUQzAgEAMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wNTEyMjIxMjE1MjFaMCMGCSqGSIb3DQEJBDEWBBR7kkvO4ekHGSjRka2jRmPzRf8HPjCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nBC8wLQIVAQHVFb4PnQgTRr48R+Yqw3WU8pq+AhQo8f2zAxuRr03omwNzFGVGgx0G3A==";
			r = sl.ChechUrl(uri, signatureBase64);
			Console.WriteLine("Check Url " + r);

			Console.ReadKey();
		}


		private sbyte[] pse;
		public string Pse {
			set { pse = copyArray(Encoding.ASCII.GetBytes(value)); }
		}
		
		private sbyte[] passwd;
		public string PsePassword {
			set { passwd = copyArray(Encoding.ASCII.GetBytes(value)); }
		}

		public int SetupProfile() {
			int r;

			// delete profile
			unsafe {
				fixed (sbyte* array_pse = pse) {
					r = SapSecuWrapper.RemoveProfile(array_pse);
					if (r != 0) {
						// TODO Log Error cannot remove profile
						return r;
					}
				}
			}

			// create profile
			unsafe {
				fixed (sbyte* array_pse = pse, array_passwd = passwd) {
					r = SapSecuWrapper.CreateProfile(array_pse, array_passwd);
					if (r != 0) {
						// TODO Log Error cannot create profile
						return r;
					}
				}
			}			

			return 0;	// OK
		}

		public int PutCertificate(byte[] certificate) {
			int r;
			
			// put certificate
			sbyte[] fileBuffer2 = copyArray(certificate);
			unsafe {
				fixed (sbyte* array_pse = pse, array_passwd = passwd, array_fileBuffer = fileBuffer2) {
					r = SapSecuWrapper.putCert(array_pse, array_passwd, array_fileBuffer, fileBuffer2.Length);
					if (r != 0) {
						// TODO Log Error cannot put certificate, errorcode r
						return r;
					}
				}
			}

			return 0;	// OK
		}

		public int ChechUrl(string uri, string signatureBase64) {
			sbyte[] uriBa = copyArray(Encoding.ASCII.GetBytes(uri));
			byte[] signature = Convert.FromBase64String(signatureBase64);
			sbyte[] signatureBa = copyArray(signature);

			unsafe {
				fixed (sbyte* array_pse = pse, array_passwd = passwd, array_uri = uriBa, array_signature = signatureBa) {
					int r = SapSecuWrapper.checkUrl(array_pse, array_passwd, array_uri, uriBa.Length, array_signature, signatureBa.Length);
					if (r != 0) {
						// TODO Log Error cannot remove profile, 5 = check failed, <0 internal error else other sapsecu error
						return r;
					}
				}
			}
			return 0;
		}

		private static byte[] ReadFile(string fileName) {
			FileStream f = new FileStream(fileName, FileMode.Open, FileAccess.Read);
			int size = (int)f.Length;
			byte[] data = new byte[size];
			size = f.Read(data, 0, size);
			f.Close();
			return data;
		}

		private static sbyte[] copyArray(byte[] b) {
			sbyte[] sb = new sbyte[b.Length];
			for (int i = 0; i < b.Length; i++)
				sb<i> = (sbyte)b<i>;
			return sb;
		}

	}

}