os/security/cryptoservices/certificateandkeymgmt/asn1/baseenc.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 * Define methods for asn1-encoding base class
    16 *
    17 */
    18 
    19 
    20 #include "base128enc.h"
    21 #include "panic.h"
    22 
    23 #include <asn1enc.h>
    24 
    25 const TUint KMaxLowNumberFormTag = 30;
    26 const TUint KMaxShortFormLength = 127;
    27 
    28 
    29 EXPORT_C CASN1EncBase::CASN1EncBase(const TTagType aType, const TASN1Class aClass)
    30 : iType(aType), iClass(aClass)
    31 	{
    32 	CalculateTagLengthDER();
    33 	}
    34 
    35 
    36 EXPORT_C CASN1EncBase::~CASN1EncBase()
    37 	{
    38 	}
    39 
    40 
    41 EXPORT_C void CASN1EncBase::ConstructL()
    42 	{
    43 	ContentsLengthChanged();
    44 	}
    45 
    46 
    47 void CASN1EncBase::ContentsLengthChanged()
    48 	{
    49 	CalculateContentsLengthDER();
    50 	CalculateLengthLengthDER();
    51 
    52 	if (iParent)
    53 		{
    54 		iParent->ContentsLengthChanged();
    55 		}
    56 	}
    57 
    58 
    59 // Set tagging scheme/tag/class
    60 EXPORT_C void CASN1EncBase::SetTag(const TTagType aType, const TASN1Class aClass)
    61 	{
    62 	iType = aType;
    63 	iClass = aClass;
    64 
    65 	CalculateTagLengthDER();
    66 	}
    67 
    68 
    69 // Gives total number of octets in the DER encoding of this object
    70 EXPORT_C TUint CASN1EncBase::LengthDER() const
    71 	{
    72 	return iTagLengthDER + iLengthLengthDER + iContentsLengthDER;
    73 	}
    74 	
    75 
    76 // Writes entire DER encoding of this object into the given buffer
    77 EXPORT_C void CASN1EncBase::WriteDERL(TDes8& aBuf, TUint& aPos) const
    78 	{
    79 	__ASSERT_ALWAYS(aBuf.Length() - STATIC_CAST(TInt, aPos) >= STATIC_CAST(TInt, LengthDER()),
    80 		Panic(KErrDescriptorTooShort));
    81 
    82 	WriteHelperL(aBuf, aPos, iTagLengthDER,      &CASN1EncBase::WriteTagDERL);
    83 	WriteHelperL(aBuf, aPos, iLengthLengthDER,   &CASN1EncBase::WriteLengthDER);
    84 	WriteHelperL(aBuf, aPos, iContentsLengthDER, &CASN1EncBase::WriteContentsDERL);
    85 	}
    86 
    87 
    88 // Internal helper method, used for efficiency
    89 void CASN1EncBase::WriteHelperL(TDes8& aBuf, TUint& aPos, const TUint aLength,
    90 									WriteFunc aWriteFunc) const
    91 	{
    92 	if (aLength)
    93 		{
    94 		// Get the middle bit of buffer we should be using
    95 		TPtr8 ptr(&aBuf[aPos], aLength, aLength);
    96 		
    97 		// Call the function to actually write the data
    98 		(this->*aWriteFunc)(ptr);
    99 		
   100 		aPos += aLength;
   101 		}
   102 	}
   103 
   104 
   105 // Give number of octets in tag section
   106 void CASN1EncBase::CalculateTagLengthDER()
   107 	{
   108 	if (iType <= KMaxLowNumberFormTag)
   109 		{
   110 		// Low tag number form
   111 		iTagLengthDER = 1;
   112 		}
   113 	else
   114 		{
   115 		// High tag number form
   116 		TASN1EncBase128DER encoder(iType);
   117 		iTagLengthDER = encoder.LengthDER() + 1;
   118 		}
   119 	}
   120 
   121 
   122 // Give number of octets in length section
   123 // Only called after contents length is worked out
   124 void CASN1EncBase::CalculateLengthLengthDER()
   125 	{
   126 	iLengthLengthDER = 1;
   127 	if (iContentsLengthDER > KMaxShortFormLength)
   128 		{
   129 		// Long form - need number of octets in base256 representation
   130 		// of length, plus 1.
   131 
   132 		TUint working = iContentsLengthDER;
   133 		do
   134 			{
   135 			++iLengthLengthDER;
   136 			}
   137 		while (working >>= 8);
   138 		}
   139 	}
   140 
   141 
   142 // Writes the tag section into the given buffer
   143 void CASN1EncBase::WriteTagDERL(TDes8& aBuf) const
   144 	{
   145 	// Write class - bits 7-8
   146 	aBuf[0] = STATIC_CAST(TUint8, iClass << 6);
   147 
   148 	// Write constructed/primitive flag in bit 6
   149 	if (IsConstructed())
   150 		{
   151 		aBuf[0] |= 0x20;
   152 		}
   153 
   154 	// Write length
   155 	if (iType <= KMaxLowNumberFormTag)
   156 		{
   157 		aBuf[0] |= iType;
   158 		}
   159 	else
   160 		{
   161 		// First byte signals more to come
   162 		aBuf[0] |= 0x1F;
   163 
   164 		// The rest we delegate
   165 		TASN1EncBase128DER encoder(iType);
   166 		TUint offset = 1;
   167 		encoder.WriteDERL(aBuf, offset);
   168 		}
   169 	}
   170 
   171 
   172 // Writes the length section into the given buffer
   173 void CASN1EncBase::WriteLengthDER(TDes8& aBuf) const
   174 	{
   175 	if (iContentsLengthDER > KMaxShortFormLength)
   176 		{
   177 		// First byte is the number of other bytes, with top bit also set
   178 		TUint octets = iLengthLengthDER - 1;
   179 
   180 		// Cast takes 8 least sig bits
   181 		aBuf[0] = STATIC_CAST(TUint8, octets);
   182 		aBuf[0] |= 0x80;
   183 
   184 		// Other bytes are base 256 representation of length, most significant first
   185 		TUint working = iContentsLengthDER;
   186 		do
   187 			{
   188 			// Cast to TUint8 takes 8 least sig bits
   189 			aBuf[octets] = STATIC_CAST(TUint8, working);
   190 			working >>= 8;
   191 			}
   192 		while (--octets);
   193 		}
   194 	else
   195 		{
   196 		// Short form, nice and easy - take least sig 8 bits with a cast
   197 		aBuf[0] = STATIC_CAST(TUint8, iContentsLengthDER);
   198 		}
   199 	}
   200 
   201 
   202 // Sets the parent (can only do this once)
   203 void CASN1EncBase::SetParent(CASN1EncBase* aParent)
   204 	{
   205 	__ASSERT_ALWAYS(iParent == 0, Panic(KErrAlreadyHasParent));
   206 	iParent = aParent;
   207 	}