Complete output example

The descriptions below take for input the following conditions:

  • A pattern, MyPatt, of u1u4c16c16u4v2*

    • By convention, the sub-function method name will be taken from 'MyPatt'

    • Field names of flags, mech, keyName, keyGroup, spec, hash and data

  •  A module, abbreviated as tCFA with ID of 0x116

  • An Answer pattern, AnswPatt

    • Note that the structure of the AnswPatt pattern is (at this point) irrelevant.

    • The AnswPatt might be passed through the automation code as a separate step, but for here it is only needed as a symbol name.

  • A package name (used for generated host code), com.utimaco.cs2.mdl.tcfa

Autogenerated C (CryptoServer SDK module destined code)

Output from compiling the pattern:

  1. The representative struct { ... } cmd; struct,

  2.  A boilerplate sub-function _ext method, around the struct, which includes the cmds_scanf() call including the pattern,

  3. Complete internal function declarations and definitions for serialization, deserialization and length computation of data in the struct, for when used as an answer structure, and

  4. Additional internal functions, methods, defines and constants that provide shortcuts on use and prevention of common errors.

Example _ext method implementation stub - no answer expected

/*

  • 01a autogenerated 2019-02-25 using

  • SFCBuffers.pl version 01d,20190225,rip

 *

  • For MyPatt using u1u4c16c16u4v2*

 *

  • For merging into an existing tcfa_ext.c look for the ::CUT:: marks.

 */

#ifndef _MyPatt_ext_c_stub_1_0_0_0

#define _MyPatt_ext_c_stub_1_0_0_0

/* Command Struct */

#include <MyPatt.h>

#include <MyPatt_int.c>

//::CUT::

/******************************************************************************

  • Module:  0x116 (tcfa)

  • tcfa_ext_mypatt

 *

  • Description  :

 *

  • Command data : SFCBuffers-generated for cmds_scanf

  • Pattern: u1u4c16c16u4v2* (MyPatt)

 *

 ******************************************************************************/

int tcfa_ext_mypatt

    (T_CMDS_HANDLE *p_hdl, int l_cmd, unsigned char*p_cmd)

{

  int           err = 0;

  struct { // MyPatt

    unsigned int   flags;                  // u1

    unsigned int   mech;                   // u4

    unsigned char *keyName;                // c16

    unsigned char *keyGroup;               // c16

    unsigned int   spec;                   // u4

    unsigned int   l_hash;                 // v2

    unsigned char *p_hash;                 //

    unsigned int   l_data;                 // *

    unsigned char *p_data;                 //

  } cmd;

  // parse command data

  if ((err = cmds_scanf(l_cmd, p_cmd, "u1u4c16c16u4v2*", sizeof(cmd), &cmd)) != 0)

        goto cleanup;

  // ... Do Work

cleanup:

  return err;

}

//::__CUT__::

#endif

----

 

 

==== Example _ext method implementation stub, including answer struct

[source,console]

.Generated C Stub (external interface code)

----

/*

  • 01a autogenerated 2019-02-25 using

  • SFCBuffers.pl version 01d,20190225,rip

 *

  • For MyPatt using u1u4c16c16u4v2*

 *

  • For merging into an existing tcfa_ext.c look for the ::CUT:: marks.

 */

#ifndef _MyPatt_ext_c_stub_1_0_0_0

#define _MyPatt_ext_c_stub_1_0_0_0

/* Command Struct */

#include <MyPatt.h>

#include <MyPatt_int.c>

//::CUT::

/******************************************************************************

  • Module:  0x116 (tcfa)

  • tcfa_ext_mypatt

 *

  • Description  :

 *

  • Command data : SFCBuffers-generated for cmds_scanf

  • Pattern: u1u4c16c16u4v2* (MyPatt)

 *

  • Answer: based on AnswPatt

 *

 ******************************************************************************/

int tcfa_ext_mypatt

    (T_CMDS_HANDLE *p_hdl, int l_cmd, unsigned char *p_cmd)

{

  int                err = 0;

  unsigned int       l_answ = 0;

  unsigned char     *p_answ = 0x0;

  struct answpatt *answ = 0x0;

   

  struct { // MyPatt

    unsigned int   flags;                  // u1

    unsigned int   mech;                   // u4

    unsigned char *keyName;                // c16

    unsigned char *keyGroup;               // c16

    unsigned int   spec;                   // u4

    unsigned int   l_hash;                 // v2

    unsigned char *p_hash;                 //

    unsigned int   l_data;                 // *

    unsigned char *p_data;                 //

  } cmd;

  // parse command data

  if ((err = cmds_scanf(l_cmd, p_cmd, "u1u4c16c16u4v2*",

                                           sizeof(cmd), &cmd)) != 0)

    goto cleanup;

  if ((answ = (struct answpatt *)os_mem_new(sizeof(struct answpatt),

                                           OS_MEM_TYPE_SD)) == 0) {

    err = E_TCFA_MALLOC;

    goto cleanup;

  }

  os_mem_set(answ, 0x0, sizeof(struct answpatt));

   

  // ... Do Work

  // ... Populate answ

  l_answ = answpatt_length( answ );

  if((err = cmds_alloc_answ(p_hdl, l_answ, &p_answ)) != 0)

    goto cleanup

  answpatt_serialize( answ , l_answ, p_answ );

                                  

cleanup:

  if (answ != 0x0)

    os_mem_del_set( answ, 0x0 );

     

  return err;

}

//::__CUT__::

#endif

----

==== Treating the pattern as an answer pattern

This is example output, covering points 3 and 4 above.  These are predominantly more useful, when 'MyPatt' is used as an answer struct, rather than when used as the input struct.

The \#defines `_TCFA_MYPATT_L_KEYNAME` and `_TCFA_MYPATT_L_KEYGROUP` are found in the MyPatt.h header.

[source,c]

.Autogenerated private methods for Serialization, etc

----

/*

  • 01a autogenerated 2019-02-25 using

  • SFCBuffers.pl version 01d,20190225,rip

 *

  • For MyPatt using u1u4c16c16u4v2*

 */

#ifndef _MyPatt_C_INT_1_0_0_0

#define _MyPatt_C_INT_1_0_0_0

#include <tCFA.h>

#include <MyPatt.h>

#include <cmds.h>

#include <load_store.h>

// u1u4c16c16u4v2*

unsigned int mypatt_length(struct mypatt *s) {

    unsigned int len = 0;

    len += 1;                           // u1 > flags

    len += 4;                           // u4 > mech

    len += _TCFA_MYPATT_L_KEYNAME;      // c16 -> keyName (16)

    len += _TCFA_MYPATT_L_KEYGROUP;     // c16 -> keyGroup (16)

    len += 4;                           // u4 > spec

    len += 2 + s->l_hash;               // v2 -> hash

    len += s->l_data;                   // * -> data

    return len;

}

// u1u4c16c16u4v2*

unsigned int mypatt_serialize (

  const struct mypatt *answ,

  unsigned int l_answ,

  unsigned char * p_answ

) {

  unsigned int err = 0;

  unsigned char * pp_answ = p_answ;

    // flags int 1

    store_int1(answ->flags, pp_answ);

    pp_answ += 1;

    // mech int 4

    store_int4(answ->mech, pp_answ);

    pp_answ += 4;

    // keyName char 16

    os_mem_cpy(pp_answ, answ->keyName, _TCFA_MYPATT_L_KEYNAME);

    pp_answ += _TCFA_MYPATT_L_KEYNAME;

    // keyGroup char 16

    os_mem_cpy(pp_answ, answ->keyGroup, _TCFA_MYPATT_L_KEYGROUP);

    pp_answ += _TCFA_MYPATT_L_KEYGROUP;

    // spec int 4

    store_int4(answ->spec, pp_answ);

    pp_answ += 4;

    // hash lvfield 2

    store_int2(answ->l_hash, pp_answ);

    pp_answ += 2;

    os_mem_cpy(pp_answ, answ->p_hash, answ->l_hash);

    pp_answ += answ->l_hash;

    // data bkkt 4

    os_mem_cpy(pp_answ, answ->p_data, answ->l_data);

    pp_answ += answ->l_data;

  if ((pp_answ - p_answ) != l_answ) {

    return E_TCFA_SERIALIZATION;

  }

  return err;

}

/* cmds_scanf of mypatt */

unsigned int mypatt_scanf (

  struct mypatt *p_stub,

  unsigned int l_data,

  char *p_data

) {

  return cmds_scanf(l_data, p_data, "u1u4c16c16u4v2*", sizeof(struct mypatt), p_stub);

}

#endif

----

 

And the respective header file:

[source,console]

.Autogenerated Header file

----

/*

  • 01a autogenerated 2019-02-25 using

  • SFCBuffers.pl version 01d,20190225,rip

 *

  • For MyPatt using u1u4c16c16u4v2*

 */

#ifndef _MyPatt_h_1_0_0_0

#define _MyPatt_h_1_0_0_0

/* Defines ---------------------------------------------------- */

#define _TCFA_MYPATT_L_KEYNAME 16   /* c16 > keyName > char */

#define _TCFA_MYPATT_L_KEYGROUP 16  /* c16 > keyGroup > char */

/* Declarations for Pattern u1u4c16c16u4v2* for use when

  • MyPatt is an ANSW */

struct mypatt { // answer using MyPatt

    unsigned int   flags;                  // u1

    unsigned int   mech;                   // u4

    unsigned char *keyName;                // c16

    unsigned char *keyGroup;               // c16

    unsigned int   spec;                   // u4

    unsigned int   l_hash;                 // v2

    unsigned char *p_hash;                 //

    unsigned int   l_data;                 // *

    unsigned char *p_data;                 //

} mypatt;

/* Len computation for Pattern u1u4c16c16u4v2*,

  • Use to determine length of previously populated answ buffer */

unsigned int mypatt_length ( structmypatt * );

/* serialization of mypatt */

unsigned int mypatt_serialize (

  const struct mypatt *,

  unsigned int,

  unsigned char *

);

/* cmds_scanf of mypatt */

unsigned int mypatt_scanf (

  struct mypatt *,

  unsigned int,

  char *

);

#define mypatt_deserialize mypatt_scanf

#endif

Autogenerated Classes in Java/C++ for the Host

For the host, what is autogenerated is OOP classes and support files.

  1. Constructors that take a serialized byte array or field values or nothing,

  2. Class members that are used in an OOP manner (via getters/setters, etc),

  3. Setters that validate data entry (c16 restricts use to 16 char lengths, v1 var-length buffers that limit themselves to 255 bytes, etc) and throw exceptions when code attempts to overstep these constraints,

  4. Support for over-loaded input value types (supply byte array or strings for an underlying variable length byte array field, for example),

  5. Serialization/deserialization methods,

  6. Serialized size determination (max size check for 256Kb, min size, exact size of current serialized size, etc),

  7. An overridden public String toString(); or debugPrint() method that is aware of the internals of the class structure (depending on language),

  8. Support for exceptions specific to what the compiler is generating (SDKInterfaceSerializationException, SDKInterfaceMaxSizeException, etc),

  9. Support for sub-classing of a common functionality super-class (class MyPatt extends SFCInterface { ... })

  10. A Test application (MyPattTest.java)

The package shown below is configurable.

Example Host MyPatt.java

package com.utimaco.cs2.mdl.tcfa;

/*

  • 01a autogenerated 2019-02-25 using

  • SFCBuffers.pl version 01d,20190225,rip

 *

  • For MyPatt using u1u4c16c16u4v2*

 */

import java.nio.ByteBuffer;

import com.utimaco.cs2.mdl.SDKInterface;

import com.utimaco.cs2.mdl.DeserializationError;

import com.utimaco.cs2.mdl.SerializationError;

public class MyPatt extendsSFCInterface {

    // Begin cmds_scanf

    protected static finalString pattern = "u1u4c16c16u4v2*";

    static final intl_keyName                = 16;    // c16

    static final intl_keyGroup               = 16;    // c16

    byte    flags = 0x0;                      // u1

    int     mech = 0x0;                       // u4

    byte [] keyName = new byte[l_keyName];    // c16

    byte [] keyGroup = new byte[l_keyGroup];  // c16

    int     spec = 0x0;                       // u4

    byte [] hash = null;                      // v2

    byte [] data = null;                      // *

    // Auto-generated constructor stubs

    public MyPatt () { }

    public MyPatt (byte [] _in) {

      try { deserialize(_in); }

      catch (DeserializationError e) { e.printStackTrace(); }

    }

    public MyPatt (

        byte _flags, int _mech, String _keyName, String _keyGroup, int _spec, String _hash, byte[] _data

    ) {

        flags(_flags);

        mech(_mech);

        keyName(_keyName);

        keyGroup(_keyGroup);

        spec(_spec);

        hash(_hash.getBytes());

        data(_data);

    }

    // *Etters

    public byte flags() { returnflags; }

    public void flags (int_in) { flags = (byte   )(_in&0x000000FF); }

    public int  mech() { returnmech; }

    public void mech (int_in) { mech = _in; }

    public byte [] keyName() { returnkeyName; }

    public void keyName (byte[] _in) {

        keyName = maxLenByteArray(_in, 16);

    }

    public void keyName (String _in) {

        keyName = maxLenByteArray(_in, 16);

    }

    public byte [] keyGroup() { returnkeyGroup; }

    public void keyGroup (byte[] _in) {

        keyGroup = maxLenByteArray(_in, 16);

    }

    public void keyGroup (String _in) {

        keyGroup = maxLenByteArray(_in, 16);

    }

    public int  spec() { returnspec; }

    public void spec (int_in) { spec = _in; }

    public byte [] hash() { returnhash; }

    public void hash (byte[] _in) { hash = _in; }

    public byte [] data() { returndata; }

    public void data (byte[] _in) { data = _in; }

    public int length() {

      int len = 0;

        len += 1;                      // flags -> u1

        len += 4;                      // mech -> u4

        len += l_keyName;              // keyName -> c16

        len += l_keyGroup;             // keyGroup -> c16

        len += 4;                      // spec -> u4

        len += 2 + hash.length;        // v2

        len += data.length;            // *

      return len;

    }

    public byte[] serialize() throwsSerializationError {

        int len = length();

        ByteBuffer bb = ByteBuffer.allocate(len);

        bb.put((byte)(flags&0xFF));

        bb.putInt(mech);

        bb.put(keyName);

        bb.put(keyGroup);

        bb.putInt(spec);

        bb.putShort((short)(hash.length & 0xFFFF));

        bb.put(hash);

        bb.put(data);

        return bb.array();

    }

    public void deserialize (byte[] bfr) throws DeserializationError {

        ByteBuffer bb = ByteBuffer.wrap(bfr);

              int len = 0x0;

        flags = bb.get();                      // flags -> u1

        mech = bb.getInt();                    // mech -> u4

        keyName = new byte[l_keyName];         // keyName -> c16

        bb.get(keyName, 0, keyName.length);

        keyGroup = new byte[l_keyGroup];       // keyGroup -> c16

        bb.get(keyGroup, 0, keyGroup.length);

        spec = bb.getInt();                    // spec -> u4

        len = bb.getShort();                   // hash -> v2

        hash = new byte[len];                  // hash -> v2

          bb.get(hash, 0, hash.length);

        len = bb.capacity() - bb.position();

          data = new byte[len];                // data -> *

          bb.get(data, 0, data.length);

    }

    public String toString() {

        // The 8 means only display the first 8 lines of the

        // entirely serialized data

        return toString("AutoGenerated com.utimaco.cs2.mdl.tcfa.MyPatt >", 8);

    }

    public String toString(String note, intmaxInitialLines) {

        try {

            StringBuilder r = new StringBuilder(xtrace(note, this.serialize()));

            String [] strings = r.toString().split("\\n");

            if (strings.length > maxInitialLines) {

                r.setLength(0);

                for (int i = 0; i < maxInitialLines; i++) { r.append(strings[i] + "\n"); }

                r.append("\t\t...\n");

            }

            r.append("flags = " + flags + "\n");

            r.append("mech = " + mech + "\n");

            r.append("keyName = \n" + xtrace(keyName, 1) + "\n");

            r.append("keyGroup = \n" + xtrace(keyGroup, 1) + "\n");

            r.append("spec = " + spec + "\n");

            r.append("hash = " + "VarL (v2) field (length: "+ hash.length + "): \n"

                        + xtrace(hash, 4) + "\n");

            r.append("data = " + "VarL ( *) field (length: "+ data.length + "): \n"

                        + xtrace(data, 4) + "\n");

            return r.toString();

        } catch (Exception e) {

            e.printStackTrace();

        }

        return "";

    }

}

The test code is lengthy and includes connection to a CryptoServer HSM, logging in, etc. It is suitable both to be called immediately, or it can be edited to provide additional/more correct input, either static or from the command line, etc.

Long term plans are to provide "fuzz" testing in line with the pattern requirements, as well as unit testing.

Autogenerated Lua (CryptoScript SDK)

Output from compiling the pattern:

  1. A complete Lua script that implements the pattern

  2. The representative ...

  3. Additional artifacts for ...

Autogenerated Lua Sub-Function Code

 

----

----