initial import
@@ -0,0 +1,191 @@
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveMacros: None
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveBitFields: None
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: false
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: true
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 99
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
QualifierAlignment: Leave
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
PackConstructorInitializers: BinPack
|
||||
BasedOnStyle: ''
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseLabels: false
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentRequires: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: true
|
||||
InsertTrailingCommas: None
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
LambdaBodyIndentation: Signature
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 10
|
||||
PenaltyBreakBeforeFirstCallParameter: 30
|
||||
PenaltyBreakComment: 10
|
||||
PenaltyBreakFirstLessLess: 0
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakString: 10
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 100
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Left
|
||||
PPIndentWidth: -1
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: false
|
||||
RemoveBracesLLVM: false
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: Never
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: Never
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: false
|
||||
AfterForeachMacros: false
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: false
|
||||
AfterOverloadedOperator: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
BitFieldColonSpacing: Both
|
||||
Standard: c++03
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
- NS_SWIFT_NAME
|
||||
- CF_SWIFT_NAME
|
||||
...
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
lib_LTLIBRARIES=libsomething.la
|
||||
libsomething_la_SOURCES=$(ASN_MODULE_SOURCES) $(ASN_MODULE_HEADERS)
|
||||
|
||||
ASN_CONVERTER_SOURCES+=test/parse.c
|
||||
ASN_MODULE_SOURCES=$(wildcard lib/asn1/*.c)
|
||||
ASN_MODULE_HEADERS=$(wildcard lib/asn1/*.h)
|
||||
|
||||
TARGET = parse
|
||||
CFLAGS += -I. -Ilib/asn1
|
||||
OBJS=${ASN_MODULE_SOURCES:.c=.o} ${ASN_CONVERTER_SOURCES:.c=.o}
|
||||
|
||||
all: regen
|
||||
|
||||
test: $(TARGET)
|
||||
|
||||
$(TARGET): regen ${OBJS}
|
||||
$(CC) $(CFLAGS) -o $(TARGET) ${OBJS} $(LDFLAGS) $(LIBS)
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
regen: regenerate-from-asn1-source
|
||||
|
||||
regenerate-from-asn1-source:
|
||||
@asn1c -D lib/asn1 -no-gen-example -pdu=all seader.asn1
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
rm -f $(OBJS)
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,45 @@
|
||||
//===-- aeabi_uldivmod.S - EABI uldivmod implementation -------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "assembly.h"
|
||||
|
||||
// struct { uint64_t quot, uint64_t rem}
|
||||
// __aeabi_uldivmod(uint64_t numerator, uint64_t denominator) {
|
||||
// uint64_t rem, quot;
|
||||
// quot = __udivmoddi4(numerator, denominator, &rem);
|
||||
// return {quot, rem};
|
||||
// }
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
#define __aeabi_uldivmod __rt_udiv64
|
||||
#endif
|
||||
|
||||
.syntax unified
|
||||
.p2align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_uldivmod)
|
||||
push {r6, lr}
|
||||
sub sp, sp, #16
|
||||
add r6, sp, #8
|
||||
str r6, [sp]
|
||||
#if defined(__MINGW32__)
|
||||
movs r6, r0
|
||||
movs r0, r2
|
||||
movs r2, r6
|
||||
movs r6, r1
|
||||
movs r1, r3
|
||||
movs r3, r6
|
||||
#endif
|
||||
bl SYMBOL_NAME(__udivmoddi4)
|
||||
ldr r2, [sp, #8]
|
||||
ldr r3, [sp, #12]
|
||||
add sp, sp, #16
|
||||
pop {r6, pc}
|
||||
END_COMPILERRT_FUNCTION(__aeabi_uldivmod)
|
||||
|
||||
NO_EXEC_STACK_DIRECTIVE
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# qv. https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/AppManifests.md
|
||||
|
||||
App(
|
||||
appid="seader",
|
||||
name="Seader",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="seader_app",
|
||||
cdefines=["APP_SEADER"],
|
||||
requires=[
|
||||
"gui", "storage", "nfc",
|
||||
],
|
||||
stack_size=7 * 1024,
|
||||
order=20,
|
||||
sources=[
|
||||
"seader.c",
|
||||
"aeabi_uldivmod.S", "bsearch.c",
|
||||
"ccid.c", "uart.c",
|
||||
"rfal_picopass.c", "scenes/*.c",
|
||||
"seader_worker.c",
|
||||
"seader_credential.c",
|
||||
"seader_icons.c",
|
||||
],
|
||||
fap_icon="icons/logo.png",
|
||||
fap_category="NFC",
|
||||
# fap_extbuild=(
|
||||
# ExtFile(
|
||||
# path="${FAP_SRC_DIR}/lib/asn1/asn_system.h",
|
||||
# command="asn1c -D ${FAP_SRC_DIR}/lib/asn1 -no-gen-example -pdu=all ${FAP_SRC_DIR}/seader.asn1"
|
||||
# ),
|
||||
# ),
|
||||
fap_private_libs=[
|
||||
Lib(
|
||||
name="asn1",
|
||||
cflags=["-Wno-error"],
|
||||
),
|
||||
],
|
||||
fap_icon_assets="icons",
|
||||
)
|
||||
@@ -0,0 +1,292 @@
|
||||
//===-- assembly.h - compiler-rt assembler support macros -----------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines macros for use in compiler-rt assembler source.
|
||||
// This file is not part of the interface of this library.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef COMPILERRT_ASSEMBLY_H
|
||||
#define COMPILERRT_ASSEMBLY_H
|
||||
|
||||
#if defined(__linux__) && defined(__CET__)
|
||||
#if __has_include(<cet.h>)
|
||||
#include <cet.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(__aarch64__)
|
||||
#define SEPARATOR %%
|
||||
#else
|
||||
#define SEPARATOR ;
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#define HIDDEN(name) .private_extern name
|
||||
#define LOCAL_LABEL(name) L_##name
|
||||
// tell linker it can break up file at label boundaries
|
||||
#define FILE_LEVEL_DIRECTIVE .subsections_via_symbols
|
||||
#define SYMBOL_IS_FUNC(name)
|
||||
#define CONST_SECTION .const
|
||||
|
||||
#define NO_EXEC_STACK_DIRECTIVE
|
||||
|
||||
#elif defined(__ELF__)
|
||||
|
||||
#define HIDDEN(name) .hidden name
|
||||
#define LOCAL_LABEL(name) .L_##name
|
||||
#define FILE_LEVEL_DIRECTIVE
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
#define SYMBOL_IS_FUNC(name) .type name,%function
|
||||
#else
|
||||
#define SYMBOL_IS_FUNC(name) .type name,@function
|
||||
#endif
|
||||
#define CONST_SECTION .section .rodata
|
||||
|
||||
#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
|
||||
defined(__linux__)
|
||||
#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
|
||||
#else
|
||||
#define NO_EXEC_STACK_DIRECTIVE
|
||||
#endif
|
||||
|
||||
#else // !__APPLE__ && !__ELF__
|
||||
|
||||
#define HIDDEN(name)
|
||||
#define LOCAL_LABEL(name) .L ## name
|
||||
#define FILE_LEVEL_DIRECTIVE
|
||||
#define SYMBOL_IS_FUNC(name) \
|
||||
.def name SEPARATOR \
|
||||
.scl 2 SEPARATOR \
|
||||
.type 32 SEPARATOR \
|
||||
.endef
|
||||
#define CONST_SECTION .section .rdata,"rd"
|
||||
|
||||
#define NO_EXEC_STACK_DIRECTIVE
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
#define FUNC_ALIGN \
|
||||
.text SEPARATOR \
|
||||
.balign 16 SEPARATOR
|
||||
#else
|
||||
#define FUNC_ALIGN
|
||||
#endif
|
||||
|
||||
// BTI and PAC gnu property note
|
||||
#define NT_GNU_PROPERTY_TYPE_0 5
|
||||
#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
|
||||
#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1
|
||||
#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2
|
||||
|
||||
#if defined(__ARM_FEATURE_BTI_DEFAULT)
|
||||
#define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
|
||||
#else
|
||||
#define BTI_FLAG 0
|
||||
#endif
|
||||
|
||||
#if __ARM_FEATURE_PAC_DEFAULT & 3
|
||||
#define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC
|
||||
#else
|
||||
#define PAC_FLAG 0
|
||||
#endif
|
||||
|
||||
#define GNU_PROPERTY(type, value) \
|
||||
.pushsection .note.gnu.property, "a" SEPARATOR \
|
||||
.p2align 3 SEPARATOR \
|
||||
.word 4 SEPARATOR \
|
||||
.word 16 SEPARATOR \
|
||||
.word NT_GNU_PROPERTY_TYPE_0 SEPARATOR \
|
||||
.asciz "GNU" SEPARATOR \
|
||||
.word type SEPARATOR \
|
||||
.word 4 SEPARATOR \
|
||||
.word value SEPARATOR \
|
||||
.word 0 SEPARATOR \
|
||||
.popsection
|
||||
|
||||
#if BTI_FLAG != 0
|
||||
#define BTI_C hint #34
|
||||
#define BTI_J hint #36
|
||||
#else
|
||||
#define BTI_C
|
||||
#define BTI_J
|
||||
#endif
|
||||
|
||||
#if (BTI_FLAG | PAC_FLAG) != 0
|
||||
#define GNU_PROPERTY_BTI_PAC \
|
||||
GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, BTI_FLAG | PAC_FLAG)
|
||||
#else
|
||||
#define GNU_PROPERTY_BTI_PAC
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM)
|
||||
#define CFI_START .cfi_startproc
|
||||
#define CFI_END .cfi_endproc
|
||||
#else
|
||||
#define CFI_START
|
||||
#define CFI_END
|
||||
#endif
|
||||
|
||||
#if defined(__arm__)
|
||||
|
||||
// Determine actual [ARM][THUMB[1][2]] ISA using compiler predefined macros:
|
||||
// - for '-mthumb -march=armv6' compiler defines '__thumb__'
|
||||
// - for '-mthumb -march=armv7' compiler defines '__thumb__' and '__thumb2__'
|
||||
#if defined(__thumb2__) || defined(__thumb__)
|
||||
#define DEFINE_CODE_STATE .thumb SEPARATOR
|
||||
#define DECLARE_FUNC_ENCODING .thumb_func SEPARATOR
|
||||
#if defined(__thumb2__)
|
||||
#define USE_THUMB_2
|
||||
#define IT(cond) it cond
|
||||
#define ITT(cond) itt cond
|
||||
#define ITE(cond) ite cond
|
||||
#else
|
||||
#define USE_THUMB_1
|
||||
#define IT(cond)
|
||||
#define ITT(cond)
|
||||
#define ITE(cond)
|
||||
#endif // defined(__thumb__2)
|
||||
#else // !defined(__thumb2__) && !defined(__thumb__)
|
||||
#define DEFINE_CODE_STATE .arm SEPARATOR
|
||||
#define DECLARE_FUNC_ENCODING
|
||||
#define IT(cond)
|
||||
#define ITT(cond)
|
||||
#define ITE(cond)
|
||||
#endif
|
||||
|
||||
#if defined(USE_THUMB_1) && defined(USE_THUMB_2)
|
||||
#error "USE_THUMB_1 and USE_THUMB_2 can't be defined together."
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
|
||||
#define ARM_HAS_BX
|
||||
#endif
|
||||
#if !defined(__ARM_FEATURE_CLZ) && !defined(USE_THUMB_1) && \
|
||||
(__ARM_ARCH >= 6 || (__ARM_ARCH == 5 && !defined(__ARM_ARCH_5__)))
|
||||
#define __ARM_FEATURE_CLZ
|
||||
#endif
|
||||
|
||||
#ifdef ARM_HAS_BX
|
||||
#define JMP(r) bx r
|
||||
#define JMPc(r, c) bx##c r
|
||||
#else
|
||||
#define JMP(r) mov pc, r
|
||||
#define JMPc(r, c) mov##c pc, r
|
||||
#endif
|
||||
|
||||
// pop {pc} can't switch Thumb mode on ARMv4T
|
||||
#if __ARM_ARCH >= 5
|
||||
#define POP_PC() pop {pc}
|
||||
#else
|
||||
#define POP_PC() \
|
||||
pop {ip}; \
|
||||
JMP(ip)
|
||||
#endif
|
||||
|
||||
#if defined(USE_THUMB_2)
|
||||
#define WIDE(op) op.w
|
||||
#else
|
||||
#define WIDE(op) op
|
||||
#endif
|
||||
#else // !defined(__arm)
|
||||
#define DECLARE_FUNC_ENCODING
|
||||
#define DEFINE_CODE_STATE
|
||||
#endif
|
||||
|
||||
#define GLUE2_(a, b) a##b
|
||||
#define GLUE(a, b) GLUE2_(a, b)
|
||||
#define GLUE2(a, b) GLUE2_(a, b)
|
||||
#define GLUE3_(a, b, c) a##b##c
|
||||
#define GLUE3(a, b, c) GLUE3_(a, b, c)
|
||||
#define GLUE4_(a, b, c, d) a##b##c##d
|
||||
#define GLUE4(a, b, c, d) GLUE4_(a, b, c, d)
|
||||
|
||||
#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
|
||||
|
||||
#ifdef VISIBILITY_HIDDEN
|
||||
#define DECLARE_SYMBOL_VISIBILITY(name) \
|
||||
HIDDEN(SYMBOL_NAME(name)) SEPARATOR
|
||||
#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) \
|
||||
HIDDEN(name) SEPARATOR
|
||||
#else
|
||||
#define DECLARE_SYMBOL_VISIBILITY(name)
|
||||
#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name)
|
||||
#endif
|
||||
|
||||
#define DEFINE_COMPILERRT_FUNCTION(name) \
|
||||
DEFINE_CODE_STATE \
|
||||
FILE_LEVEL_DIRECTIVE SEPARATOR \
|
||||
.globl SYMBOL_NAME(name) SEPARATOR \
|
||||
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
||||
DECLARE_SYMBOL_VISIBILITY(name) \
|
||||
DECLARE_FUNC_ENCODING \
|
||||
SYMBOL_NAME(name):
|
||||
|
||||
#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \
|
||||
DEFINE_CODE_STATE \
|
||||
FILE_LEVEL_DIRECTIVE SEPARATOR \
|
||||
.globl SYMBOL_NAME(name) SEPARATOR \
|
||||
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
||||
DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
|
||||
.thumb_func SEPARATOR \
|
||||
SYMBOL_NAME(name):
|
||||
|
||||
#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \
|
||||
DEFINE_CODE_STATE \
|
||||
FILE_LEVEL_DIRECTIVE SEPARATOR \
|
||||
.globl SYMBOL_NAME(name) SEPARATOR \
|
||||
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
||||
HIDDEN(SYMBOL_NAME(name)) SEPARATOR \
|
||||
DECLARE_FUNC_ENCODING \
|
||||
SYMBOL_NAME(name):
|
||||
|
||||
#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \
|
||||
DEFINE_CODE_STATE \
|
||||
.globl name SEPARATOR \
|
||||
SYMBOL_IS_FUNC(name) SEPARATOR \
|
||||
HIDDEN(name) SEPARATOR \
|
||||
DECLARE_FUNC_ENCODING \
|
||||
name:
|
||||
|
||||
#define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name) \
|
||||
DEFINE_CODE_STATE \
|
||||
FUNC_ALIGN \
|
||||
.globl name SEPARATOR \
|
||||
SYMBOL_IS_FUNC(name) SEPARATOR \
|
||||
DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) SEPARATOR \
|
||||
CFI_START SEPARATOR \
|
||||
DECLARE_FUNC_ENCODING \
|
||||
name: SEPARATOR BTI_C
|
||||
|
||||
#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \
|
||||
.globl SYMBOL_NAME(name) SEPARATOR \
|
||||
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
|
||||
DECLARE_SYMBOL_VISIBILITY(SYMBOL_NAME(name)) SEPARATOR \
|
||||
.set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR
|
||||
|
||||
#if defined(__ARM_EABI__)
|
||||
#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \
|
||||
DEFINE_COMPILERRT_FUNCTION_ALIAS(aeabi_name, name)
|
||||
#else
|
||||
#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name)
|
||||
#endif
|
||||
|
||||
#ifdef __ELF__
|
||||
#define END_COMPILERRT_FUNCTION(name) \
|
||||
.size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
|
||||
#define END_COMPILERRT_OUTLINE_FUNCTION(name) \
|
||||
CFI_END SEPARATOR \
|
||||
.size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
|
||||
#else
|
||||
#define END_COMPILERRT_FUNCTION(name)
|
||||
#define END_COMPILERRT_OUTLINE_FUNCTION(name) \
|
||||
CFI_END
|
||||
#endif
|
||||
|
||||
#endif // COMPILERRT_ASSEMBLY_H
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)bsearch.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/lib/libc/stdlib/bsearch.c,v 1.4 2007/01/09 00:28:09 imp Exp $");
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Perform a binary search.
|
||||
*
|
||||
* The code below is a bit sneaky. After a comparison fails, we
|
||||
* divide the work in half by moving either left or right. If lim
|
||||
* is odd, moving left simply involves halving lim: e.g., when lim
|
||||
* is 5 we look at item 2, so we change lim to 2 so that we will
|
||||
* look at items 0 & 1. If lim is even, the same applies. If lim
|
||||
* is odd, moving right again involes halving lim, this time moving
|
||||
* the base up one item past p: e.g., when lim is 5 we change base
|
||||
* to item 3 and make lim 2 so that we will look at items 3 and 4.
|
||||
* If lim is even, however, we have to shrink it by one before
|
||||
* halving: e.g., when lim is 4, we still looked at item 2, so we
|
||||
* have to make lim 3, then halve, obtaining 1, so that we will only
|
||||
* look at item 3.
|
||||
*/
|
||||
void* bsearch(key, base0, nmemb, size, compar) const void* key;
|
||||
const void* base0;
|
||||
size_t nmemb;
|
||||
size_t size;
|
||||
int (*compar)(const void*, const void*);
|
||||
{
|
||||
const char* base = base0;
|
||||
size_t lim;
|
||||
int cmp;
|
||||
const void* p;
|
||||
|
||||
for(lim = nmemb; lim != 0; lim >>= 1) {
|
||||
p = base + (lim >> 1) * size;
|
||||
cmp = (*compar)(key, p);
|
||||
if(cmp == 0) return ((void*)p);
|
||||
if(cmp > 0) { /* key > p: move right */
|
||||
base = (char*)p + size;
|
||||
lim--;
|
||||
} /* else move left */
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#ifdef __BLOCKS__
|
||||
void* bsearch_b(key, base0, nmemb, size, compar) const void* key;
|
||||
const void* base0;
|
||||
size_t nmemb;
|
||||
size_t size;
|
||||
int (^compar)(const void*, const void*);
|
||||
{
|
||||
const char* base = base0;
|
||||
size_t lim;
|
||||
int cmp;
|
||||
const void* p;
|
||||
|
||||
for(lim = nmemb; lim != 0; lim >>= 1) {
|
||||
p = base + (lim >> 1) * size;
|
||||
cmp = compar(key, p);
|
||||
if(cmp == 0) return ((void*)p);
|
||||
if(cmp > 0) { /* key > p: move right */
|
||||
base = (char*)p + size;
|
||||
lim--;
|
||||
} /* else move left */
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
#endif /* __BLOCKS__ */
|
||||
@@ -0,0 +1,251 @@
|
||||
#include "seader_i.h"
|
||||
|
||||
#define TAG "SeaderCCID"
|
||||
|
||||
bool hasSAM = false;
|
||||
const uint8_t SAM_ATR[] =
|
||||
{0x3b, 0x95, 0x96, 0x80, 0xb1, 0xfe, 0x55, 0x1f, 0xc7, 0x47, 0x72, 0x61, 0x63, 0x65, 0x13};
|
||||
const uint8_t SAM_ATR2[] = {0x3b, 0x90, 0x96, 0x91, 0x81, 0xb1, 0xfe, 0x55, 0x1f, 0xc7, 0xd4};
|
||||
|
||||
uint8_t slot = 0;
|
||||
uint8_t sequence = 0;
|
||||
uint8_t retries = 3;
|
||||
uint8_t getSequence() {
|
||||
if(sequence > 254) {
|
||||
sequence = 0;
|
||||
}
|
||||
return sequence++;
|
||||
}
|
||||
|
||||
size_t addLRC(uint8_t* data, size_t len) {
|
||||
uint8_t lrc = 0;
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
lrc ^= data[i];
|
||||
}
|
||||
data[len] = lrc;
|
||||
return len + 1;
|
||||
}
|
||||
|
||||
void PC_to_RDR_IccPowerOn(SeaderUartBridge* seader_uart) {
|
||||
memset(seader_uart->tx_buf, 0, SEADER_UART_RX_BUF_SIZE);
|
||||
seader_uart->tx_buf[0] = SYNC;
|
||||
seader_uart->tx_buf[1] = CTRL;
|
||||
seader_uart->tx_buf[2 + 0] = CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn;
|
||||
|
||||
seader_uart->tx_buf[2 + 5] = slot;
|
||||
seader_uart->tx_buf[2 + 6] = getSequence();
|
||||
seader_uart->tx_buf[2 + 7] = 2; //power
|
||||
|
||||
seader_uart->tx_len = addLRC(seader_uart->tx_buf, 2 + 10);
|
||||
furi_thread_flags_set(furi_thread_get_id(seader_uart->tx_thread), WorkerEvtSamRx);
|
||||
}
|
||||
|
||||
void PC_to_RDR_GetSlotStatus(SeaderUartBridge* seader_uart) {
|
||||
memset(seader_uart->tx_buf, 0, SEADER_UART_RX_BUF_SIZE);
|
||||
seader_uart->tx_buf[0] = SYNC;
|
||||
seader_uart->tx_buf[1] = CTRL;
|
||||
seader_uart->tx_buf[2 + 0] = CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus;
|
||||
seader_uart->tx_buf[2 + 5] = slot;
|
||||
seader_uart->tx_buf[2 + 6] = getSequence();
|
||||
|
||||
seader_uart->tx_len = addLRC(seader_uart->tx_buf, 2 + 10);
|
||||
furi_thread_flags_set(furi_thread_get_id(seader_uart->tx_thread), WorkerEvtSamRx);
|
||||
}
|
||||
|
||||
void PC_to_RDR_SetParameters(SeaderUartBridge* seader_uart) {
|
||||
uint8_t T1 = 1;
|
||||
memset(seader_uart->tx_buf, 0, SEADER_UART_RX_BUF_SIZE);
|
||||
seader_uart->tx_buf[0] = SYNC;
|
||||
seader_uart->tx_buf[1] = CTRL;
|
||||
seader_uart->tx_buf[2 + 0] = CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters;
|
||||
seader_uart->tx_buf[2 + 1] = 0;
|
||||
seader_uart->tx_buf[2 + 5] = slot;
|
||||
seader_uart->tx_buf[2 + 6] = getSequence();
|
||||
seader_uart->tx_buf[2 + 7] = T1;
|
||||
seader_uart->tx_buf[2 + 8] = 0;
|
||||
seader_uart->tx_buf[2 + 9] = 0;
|
||||
|
||||
seader_uart->tx_len = addLRC(seader_uart->tx_buf, 2 + 10);
|
||||
|
||||
furi_thread_flags_set(furi_thread_get_id(seader_uart->tx_thread), WorkerEvtSamRx);
|
||||
}
|
||||
|
||||
void PC_to_RDR_GetParameters(SeaderUartBridge* seader_uart) {
|
||||
memset(seader_uart->tx_buf, 0, SEADER_UART_RX_BUF_SIZE);
|
||||
seader_uart->tx_buf[0] = SYNC;
|
||||
seader_uart->tx_buf[1] = CTRL;
|
||||
seader_uart->tx_buf[2 + 0] = CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters;
|
||||
seader_uart->tx_buf[2 + 1] = 0;
|
||||
seader_uart->tx_buf[2 + 5] = slot;
|
||||
seader_uart->tx_buf[2 + 6] = getSequence();
|
||||
seader_uart->tx_buf[2 + 7] = 0;
|
||||
seader_uart->tx_buf[2 + 8] = 0;
|
||||
seader_uart->tx_buf[2 + 9] = 0;
|
||||
|
||||
seader_uart->tx_len = addLRC(seader_uart->tx_buf, 2 + 10);
|
||||
|
||||
furi_thread_flags_set(furi_thread_get_id(seader_uart->tx_thread), WorkerEvtSamRx);
|
||||
}
|
||||
|
||||
void PC_to_RDR_XfrBlock(SeaderUartBridge* seader_uart, uint8_t* data, size_t len) {
|
||||
memset(seader_uart->tx_buf, 0, SEADER_UART_RX_BUF_SIZE);
|
||||
seader_uart->tx_buf[0] = SYNC;
|
||||
seader_uart->tx_buf[1] = CTRL;
|
||||
seader_uart->tx_buf[2 + 0] = CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock;
|
||||
seader_uart->tx_buf[2 + 1] = len;
|
||||
seader_uart->tx_buf[2 + 5] = slot;
|
||||
seader_uart->tx_buf[2 + 6] = getSequence();
|
||||
seader_uart->tx_buf[2 + 7] = 5;
|
||||
seader_uart->tx_buf[2 + 8] = 0;
|
||||
seader_uart->tx_buf[2 + 9] = 0;
|
||||
|
||||
memcpy(seader_uart->tx_buf + 2 + 10, data, len);
|
||||
seader_uart->tx_len = addLRC(seader_uart->tx_buf, 2 + 10 + len);
|
||||
// FURI_LOG_I(TAG, "PC_to_RDR_XfrBlock %d bytes", seader_uart->tx_len);
|
||||
|
||||
furi_thread_flags_set(furi_thread_get_id(seader_uart->tx_thread), WorkerEvtSamRx);
|
||||
}
|
||||
|
||||
size_t processCCID(SeaderWorker* seader_worker, uint8_t* cmd, size_t cmd_len) {
|
||||
SeaderUartBridge* seader_uart = seader_worker->uart;
|
||||
CCID_Message message;
|
||||
message.consumed = 0;
|
||||
|
||||
char display[SEADER_UART_RX_BUF_SIZE * 2 + 1] = {0};
|
||||
for(uint8_t i = 0; i < cmd_len; i++) {
|
||||
snprintf(display + (i * 2), sizeof(display), "%02x", cmd[i]);
|
||||
}
|
||||
FURI_LOG_D(TAG, "CCID %d: %s", cmd_len, display);
|
||||
|
||||
if(cmd_len == 2) {
|
||||
if(cmd[0] == CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange) {
|
||||
switch(cmd[1]) {
|
||||
case CARD_OUT:
|
||||
FURI_LOG_D(TAG, "Card removed");
|
||||
break;
|
||||
case CARD_IN_1:
|
||||
FURI_LOG_D(TAG, "Card Inserted (1)");
|
||||
slot = 0;
|
||||
sequence = 0;
|
||||
FURI_LOG_D(TAG, "Sending Power On");
|
||||
PC_to_RDR_IccPowerOn(seader_uart);
|
||||
break;
|
||||
case CARD_IN_2:
|
||||
FURI_LOG_D(TAG, "Card Inserted (2)");
|
||||
slot = 1;
|
||||
sequence = 0;
|
||||
FURI_LOG_D(TAG, "Sending Power On");
|
||||
PC_to_RDR_IccPowerOn(seader_uart);
|
||||
break;
|
||||
case CARD_IN_BOTH:
|
||||
FURI_LOG_W(TAG, "Loading 2 cards not supported");
|
||||
break;
|
||||
};
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
while(cmd_len >= 3 && cmd[0] == SYNC && cmd[1] == NAK) {
|
||||
// 031516
|
||||
FURI_LOG_W(TAG, "NAK");
|
||||
cmd += 3;
|
||||
cmd_len -= 3;
|
||||
message.consumed += 3;
|
||||
}
|
||||
|
||||
while(cmd_len > 2 && (cmd[0] != SYNC || cmd[1] != CTRL)) {
|
||||
FURI_LOG_W(TAG, "invalid start");
|
||||
cmd += 1;
|
||||
cmd_len -= 1;
|
||||
message.consumed += 1;
|
||||
}
|
||||
|
||||
if(cmd_len > 12 && cmd[0] == SYNC && cmd[1] == CTRL) {
|
||||
uint8_t* ccid = cmd + 2;
|
||||
message.bMessageType = ccid[0];
|
||||
message.dwLength = *((uint32_t*)(ccid + 1));
|
||||
message.bStatus = ccid[7];
|
||||
message.bError = ccid[8];
|
||||
message.payload = ccid + 10;
|
||||
|
||||
if(cmd_len < 2 + 10 + message.dwLength + 1) {
|
||||
return message.consumed;
|
||||
}
|
||||
message.consumed += 2 + 10 + message.dwLength + 1;
|
||||
|
||||
//0306 81 00000000 0000 0200 01 87
|
||||
//0306 81 00000000 0000 0100 01 84
|
||||
if(message.bMessageType == CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus) {
|
||||
uint8_t status = (message.bStatus & BMICCSTATUS_MASK);
|
||||
if(status == 0 || status == 1) {
|
||||
FURI_LOG_D(TAG, "Sending Power On");
|
||||
PC_to_RDR_IccPowerOn(seader_uart);
|
||||
return message.consumed;
|
||||
} else if(status == 2) {
|
||||
FURI_LOG_W(TAG, "No ICC is present [retries %d]", retries);
|
||||
if(retries-- > 1) {
|
||||
furi_delay_ms(100);
|
||||
PC_to_RDR_GetSlotStatus(seader_uart);
|
||||
} else {
|
||||
if(seader_worker->callback) {
|
||||
seader_worker->callback(
|
||||
SeaderWorkerEventSamMissing, seader_worker->context);
|
||||
}
|
||||
}
|
||||
return message.consumed;
|
||||
}
|
||||
}
|
||||
|
||||
//0306 80 00000000 0001 42fe 00 38
|
||||
if(message.bStatus == 0x41 && message.bError == 0xfe) {
|
||||
FURI_LOG_W(TAG, "card probably upside down");
|
||||
if(seader_worker->callback) {
|
||||
seader_worker->callback(SeaderWorkerEventSamMissing, seader_worker->context);
|
||||
}
|
||||
return message.consumed;
|
||||
}
|
||||
if(message.bStatus == 0x42 && message.bError == 0xfe) {
|
||||
FURI_LOG_W(TAG, "No card");
|
||||
if(seader_worker->callback) {
|
||||
seader_worker->callback(SeaderWorkerEventSamMissing, seader_worker->context);
|
||||
}
|
||||
return message.consumed;
|
||||
}
|
||||
if(message.bError != 0) {
|
||||
FURI_LOG_W(TAG, "CCID error");
|
||||
message.consumed = cmd_len;
|
||||
if(seader_worker->callback) {
|
||||
seader_worker->callback(SeaderWorkerEventSamMissing, seader_worker->context);
|
||||
}
|
||||
return message.consumed;
|
||||
}
|
||||
|
||||
if(message.bMessageType == CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock) {
|
||||
if(hasSAM) {
|
||||
seader_worker_process_message(seader_worker, &message);
|
||||
} else {
|
||||
if(memcmp(SAM_ATR, message.payload, sizeof(SAM_ATR)) == 0) {
|
||||
FURI_LOG_I(TAG, "SAM ATR!");
|
||||
hasSAM = true;
|
||||
if(seader_worker->callback) {
|
||||
seader_worker->callback(
|
||||
SeaderWorkerEventSamPresent, seader_worker->context);
|
||||
}
|
||||
} else if(memcmp(SAM_ATR2, message.payload, sizeof(SAM_ATR2)) == 0) {
|
||||
FURI_LOG_I(TAG, "SAM ATR2!");
|
||||
hasSAM = true;
|
||||
if(seader_worker->callback) {
|
||||
seader_worker->callback(
|
||||
SeaderWorkerEventSamPresent, seader_worker->context);
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_W(TAG, "Unknown ATR");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_W(TAG, "Unhandled CCID message type %d", message.bMessageType);
|
||||
}
|
||||
}
|
||||
|
||||
return message.consumed;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <stdlib.h> // malloc
|
||||
#include <stdint.h> // uint32_t
|
||||
#include <stdarg.h> // __VA_ARGS__
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sub.h"
|
||||
#include "seader_worker_i.h"
|
||||
|
||||
#define SYNC (0x03)
|
||||
#define CTRL (0x06)
|
||||
#define NAK (0x15)
|
||||
|
||||
#define BMICCSTATUS_MASK 0x03
|
||||
#define CARD_OUT 0x02
|
||||
#define CARD_IN_1 0x03
|
||||
#define CARD_IN_2 0x06
|
||||
#define CARD_IN_BOTH 0x07
|
||||
|
||||
/*
|
||||
* * BULK_OUT messages from PC to Reader
|
||||
* * Defined in CCID Rev 1.1 6.1 (page 26)
|
||||
* */
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn 0x62
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff 0x63
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus 0x65
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock 0x6f
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters 0x6c
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters 0x6d
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters 0x61
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_Escape 0x6b
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_IccClock 0x6e
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU 0x6a
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_Secure 0x69
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical 0x71
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_Abort 0x72
|
||||
#define CCID_MESSAGE_TYPE_PC_to_RDR_SetDataRateAndClockFrequency 0x73
|
||||
/*
|
||||
* * BULK_IN messages from Reader to PC
|
||||
* * Defined in CCID Rev 1.1 6.2 (page 48)
|
||||
* */
|
||||
#define CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock 0x80
|
||||
#define CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus 0x81
|
||||
#define CCID_MESSAGE_TYPE_RDR_to_PC_Parameters 0x82
|
||||
#define CCID_MESSAGE_TYPE_RDR_to_PC_Escape 0x83
|
||||
#define CCID_MESSAGE_TYPE_RDR_to_PC_DataRateAndClockFrequency 0x84
|
||||
/*
|
||||
* * INTERRUPT_IN messages from Reader to PC
|
||||
* * Defined in CCID Rev 1.1 6.3 (page 56)
|
||||
* */
|
||||
#define CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange 0x50
|
||||
#define CCID_MESSAGE_TYPE_RDR_to_PC_HardwareError 0x51
|
||||
|
||||
/* Status codes that go in bStatus (see 6.2.6) */
|
||||
enum {
|
||||
ICC_STATUS_PRESENT_ACTIVE = 0,
|
||||
ICC_STATUS_PRESENT_INACTIVE,
|
||||
ICC_STATUS_NOT_PRESENT
|
||||
};
|
||||
enum {
|
||||
COMMAND_STATUS_NO_ERROR = 0,
|
||||
COMMAND_STATUS_FAILED,
|
||||
COMMAND_STATUS_TIME_EXTENSION_REQUIRED
|
||||
};
|
||||
/* Error codes that go in bError (see 6.2.6) */
|
||||
enum {
|
||||
ERROR_CMD_NOT_SUPPORTED = 0,
|
||||
ERROR_CMD_ABORTED = -1,
|
||||
ERROR_ICC_MUTE = -2,
|
||||
ERROR_XFR_PARITY_ERROR = -3,
|
||||
ERROR_XFR_OVERRUN = -4,
|
||||
ERROR_HW_ERROR = -5,
|
||||
};
|
||||
|
||||
struct CCID_Message {
|
||||
uint8_t bMessageType;
|
||||
uint32_t dwLength;
|
||||
uint8_t bSlot;
|
||||
uint8_t bSeq;
|
||||
uint8_t bStatus;
|
||||
uint8_t bError;
|
||||
|
||||
uint8_t *payload;
|
||||
size_t consumed;
|
||||
};
|
||||
|
||||
void PC_to_RDR_IccPowerOn(SeaderUartBridge* seader_uart);
|
||||
void PC_to_RDR_GetSlotStatus(SeaderUartBridge* seader_uart);
|
||||
void PC_to_RDR_SetParameters(SeaderUartBridge* seader_uart);
|
||||
void PC_to_RDR_GetParameters(SeaderUartBridge* seader_uart);
|
||||
void PC_to_RDR_XfrBlock(SeaderUartBridge* seader_uart, uint8_t *data, size_t len);
|
||||
size_t processCCID(SeaderWorker* seader_worker, uint8_t* cmd, size_t cmd_len);
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
## References
|
||||
|
||||
| pdf | source |
|
||||
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
||||
| omnikey_5025_cl_software_developer_guide_mn_en.pdf.pdf | https://www.virtualsecurity.nl/amfile/file/download/file/18/product/1892/ |
|
||||
| omnikey_5326_dfr_softwaredeveloperguide.pdf | https://www.hidglobal.com/sites/default/files/documentlibrary/omnikey_5326_dfr_softwaredeveloperguide.pdf |
|
||||
| omnikey_5027_software_developer_guide.pdf | https://www.hidglobal.com/sites/default/files/documentlibrary/omnikey_5027_software_developer_guide.pdf |
|
||||
| User-Manual/User-Manual-1896753.pdf | https://fccid.io/JQ6-SE3200/User-Manual/User-Manual-1896753.pdf |
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 304 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 312 B |
@@ -0,0 +1,2 @@
|
||||
Makefile.am.*
|
||||
converter-example.mk
|
||||
@@ -0,0 +1,652 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <BIT_STRING.h>
|
||||
#include <asn_internal.h>
|
||||
|
||||
/*
|
||||
* BIT STRING basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
|
||||
};
|
||||
asn_OCTET_STRING_specifics_t asn_SPC_BIT_STRING_specs = {
|
||||
sizeof(BIT_STRING_t),
|
||||
offsetof(BIT_STRING_t, _asn_ctx),
|
||||
ASN_OSUBV_BIT
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_BIT_STRING = {
|
||||
OCTET_STRING_free, /* Implemented in terms of OCTET STRING */
|
||||
BIT_STRING_print,
|
||||
BIT_STRING_compare,
|
||||
OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */
|
||||
OCTET_STRING_decode_xer_binary,
|
||||
BIT_STRING_encode_xer,
|
||||
#ifdef ASN_DISABLE_OER_SUPPORT
|
||||
0,
|
||||
0,
|
||||
#else
|
||||
BIT_STRING_decode_oer,
|
||||
BIT_STRING_encode_oer,
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
||||
#ifdef ASN_DISABLE_PER_SUPPORT
|
||||
0,
|
||||
0,
|
||||
#else
|
||||
BIT_STRING_decode_uper, /* Unaligned PER decoder */
|
||||
BIT_STRING_encode_uper, /* Unaligned PER encoder */
|
||||
#endif /* ASN_DISABLE_PER_SUPPORT */
|
||||
BIT_STRING_random_fill,
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_BIT_STRING = {
|
||||
"BIT STRING",
|
||||
"BIT_STRING",
|
||||
&asn_OP_BIT_STRING,
|
||||
asn_DEF_BIT_STRING_tags,
|
||||
sizeof(asn_DEF_BIT_STRING_tags)
|
||||
/ sizeof(asn_DEF_BIT_STRING_tags[0]),
|
||||
asn_DEF_BIT_STRING_tags, /* Same as above */
|
||||
sizeof(asn_DEF_BIT_STRING_tags)
|
||||
/ sizeof(asn_DEF_BIT_STRING_tags[0]),
|
||||
{ 0, 0, BIT_STRING_constraint },
|
||||
0, 0, /* No members */
|
||||
&asn_SPC_BIT_STRING_specs
|
||||
};
|
||||
|
||||
/*
|
||||
* BIT STRING generic constraint.
|
||||
*/
|
||||
int
|
||||
BIT_STRING_constraint(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
|
||||
if(st && st->buf) {
|
||||
if((st->size == 0 && st->bits_unused)
|
||||
|| st->bits_unused < 0 || st->bits_unused > 7) {
|
||||
ASN__CTFAIL(app_key, td, sptr,
|
||||
"%s: invalid padding byte (%s:%d)",
|
||||
td->name, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ASN__CTFAIL(app_key, td, sptr,
|
||||
"%s: value not given (%s:%d)",
|
||||
td->name, __FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *_bit_pattern[16] = {
|
||||
"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
|
||||
"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
|
||||
};
|
||||
|
||||
asn_enc_rval_t
|
||||
BIT_STRING_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
asn_enc_rval_t er;
|
||||
char scratch[128];
|
||||
char *p = scratch;
|
||||
char *scend = scratch + (sizeof(scratch) - 10);
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
int xcan = (flags & XER_F_CANONICAL);
|
||||
uint8_t *buf;
|
||||
uint8_t *end;
|
||||
|
||||
if(!st || !st->buf)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
er.encoded = 0;
|
||||
|
||||
buf = st->buf;
|
||||
end = buf + st->size - 1; /* Last byte is special */
|
||||
|
||||
/*
|
||||
* Binary dump
|
||||
*/
|
||||
for(; buf < end; buf++) {
|
||||
int v = *buf;
|
||||
int nline = xcan?0:(((buf - st->buf) % 8) == 0);
|
||||
if(p >= scend || nline) {
|
||||
ASN__CALLBACK(scratch, p - scratch);
|
||||
p = scratch;
|
||||
if(nline) ASN__TEXT_INDENT(1, ilevel);
|
||||
}
|
||||
memcpy(p + 0, _bit_pattern[v >> 4], 4);
|
||||
memcpy(p + 4, _bit_pattern[v & 0x0f], 4);
|
||||
p += 8;
|
||||
}
|
||||
|
||||
if(!xcan && ((buf - st->buf) % 8) == 0)
|
||||
ASN__TEXT_INDENT(1, ilevel);
|
||||
ASN__CALLBACK(scratch, p - scratch);
|
||||
p = scratch;
|
||||
|
||||
if(buf == end) {
|
||||
int v = *buf;
|
||||
int ubits = st->bits_unused;
|
||||
int i;
|
||||
for(i = 7; i >= ubits; i--)
|
||||
*p++ = (v & (1 << i)) ? 0x31 : 0x30;
|
||||
ASN__CALLBACK(scratch, p - scratch);
|
||||
}
|
||||
|
||||
if(!xcan) ASN__TEXT_INDENT(1, ilevel - 1);
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
cb_failed:
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* BIT STRING specific contents printer.
|
||||
*/
|
||||
int
|
||||
BIT_STRING_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const char * const h2c = "0123456789ABCDEF";
|
||||
char scratch[64];
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
uint8_t *buf;
|
||||
uint8_t *end;
|
||||
char *p = scratch;
|
||||
|
||||
(void)td; /* Unused argument */
|
||||
|
||||
if(!st || !st->buf)
|
||||
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
|
||||
|
||||
ilevel++;
|
||||
buf = st->buf;
|
||||
end = buf + st->size;
|
||||
|
||||
/*
|
||||
* Hexadecimal dump.
|
||||
*/
|
||||
for(; buf < end; buf++) {
|
||||
if((buf - st->buf) % 16 == 0 && (st->size > 16)
|
||||
&& buf != st->buf) {
|
||||
_i_INDENT(1);
|
||||
/* Dump the string */
|
||||
if(cb(scratch, p - scratch, app_key) < 0) return -1;
|
||||
p = scratch;
|
||||
}
|
||||
*p++ = h2c[*buf >> 4];
|
||||
*p++ = h2c[*buf & 0x0F];
|
||||
*p++ = 0x20;
|
||||
}
|
||||
|
||||
if(p > scratch) {
|
||||
p--; /* Eat the tailing space */
|
||||
|
||||
if((st->size > 16)) {
|
||||
_i_INDENT(1);
|
||||
}
|
||||
|
||||
/* Dump the incomplete 16-bytes row */
|
||||
if(cb(scratch, p - scratch, app_key) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(st->bits_unused) {
|
||||
int ret = snprintf(scratch, sizeof(scratch), " (%d bit%s unused)",
|
||||
st->bits_unused, st->bits_unused == 1 ? "" : "s");
|
||||
assert(ret > 0 && ret < (ssize_t)sizeof(scratch));
|
||||
if(ret > 0 && ret < (ssize_t)sizeof(scratch)
|
||||
&& cb(scratch, ret, app_key) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-destructively remove the trailing 0-bits from the given bit string.
|
||||
*/
|
||||
static const BIT_STRING_t *
|
||||
BIT_STRING__compactify(const BIT_STRING_t *st, BIT_STRING_t *tmp) {
|
||||
const uint8_t *b;
|
||||
union {
|
||||
const uint8_t *c_buf;
|
||||
uint8_t *nc_buf;
|
||||
} unconst;
|
||||
|
||||
if(st->size == 0) {
|
||||
assert(st->bits_unused == 0);
|
||||
return st;
|
||||
} else {
|
||||
for(b = &st->buf[st->size - 1]; b > st->buf && *b == 0; b--) {
|
||||
;
|
||||
}
|
||||
/* b points to the last byte which may contain data */
|
||||
if(*b) {
|
||||
int unused = 7;
|
||||
uint8_t v = *b;
|
||||
v &= -(int8_t)v;
|
||||
if(v & 0x0F) unused -= 4;
|
||||
if(v & 0x33) unused -= 2;
|
||||
if(v & 0x55) unused -= 1;
|
||||
tmp->size = b-st->buf + 1;
|
||||
tmp->bits_unused = unused;
|
||||
} else {
|
||||
tmp->size = b-st->buf;
|
||||
tmp->bits_unused = 0;
|
||||
}
|
||||
|
||||
assert(b >= st->buf);
|
||||
}
|
||||
|
||||
unconst.c_buf = st->buf;
|
||||
tmp->buf = unconst.nc_buf;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lexicographically compare the common prefix of both strings,
|
||||
* and if it is the same return -1 for the smallest string.
|
||||
*/
|
||||
int
|
||||
BIT_STRING_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
|
||||
const void *bptr) {
|
||||
/*
|
||||
* Remove information about trailing bits, since
|
||||
* X.680 (08/2015) #22.7 "ensure that different semantics are not"
|
||||
* "associated with [values that differ only in] the trailing 0 bits."
|
||||
*/
|
||||
BIT_STRING_t compact_a, compact_b;
|
||||
const BIT_STRING_t *a = BIT_STRING__compactify(aptr, &compact_a);
|
||||
const BIT_STRING_t *b = BIT_STRING__compactify(bptr, &compact_b);
|
||||
const asn_OCTET_STRING_specifics_t *specs = td->specifics;
|
||||
|
||||
assert(specs && specs->subvariant == ASN_OSUBV_BIT);
|
||||
|
||||
if(a && b) {
|
||||
size_t common_prefix_size = a->size <= b->size ? a->size : b->size;
|
||||
int ret = memcmp(a->buf, b->buf, common_prefix_size);
|
||||
if(ret == 0) {
|
||||
/* Figure out which string with equal prefixes is longer. */
|
||||
if(a->size < b->size) {
|
||||
return -1;
|
||||
} else if(a->size > b->size) {
|
||||
return 1;
|
||||
} else {
|
||||
/* Figure out how many unused bits */
|
||||
if(a->bits_unused > b->bits_unused) {
|
||||
return -1;
|
||||
} else if(a->bits_unused < b->bits_unused) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
} else if(!a && !b) {
|
||||
return 0;
|
||||
} else if(!a) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ASN_DISABLE_PER_SUPPORT
|
||||
|
||||
#undef RETURN
|
||||
#define RETURN(_code) \
|
||||
do { \
|
||||
asn_dec_rval_t tmprval; \
|
||||
tmprval.code = _code; \
|
||||
tmprval.consumed = consumed_myself; \
|
||||
return tmprval; \
|
||||
} while(0)
|
||||
|
||||
static asn_per_constraint_t asn_DEF_BIT_STRING_constraint_size = {
|
||||
APC_SEMI_CONSTRAINED, -1, -1, 0, 0};
|
||||
|
||||
asn_dec_rval_t
|
||||
BIT_STRING_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr,
|
||||
asn_per_data_t *pd) {
|
||||
const asn_OCTET_STRING_specifics_t *specs = td->specifics
|
||||
? (const asn_OCTET_STRING_specifics_t *)td->specifics
|
||||
: &asn_SPC_BIT_STRING_specs;
|
||||
const asn_per_constraints_t *pc =
|
||||
constraints ? constraints : td->encoding_constraints.per_constraints;
|
||||
const asn_per_constraint_t *csiz;
|
||||
asn_dec_rval_t rval = { RC_OK, 0 };
|
||||
BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
|
||||
ssize_t consumed_myself = 0;
|
||||
int repeat;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
|
||||
if(pc) {
|
||||
csiz = &pc->size;
|
||||
} else {
|
||||
csiz = &asn_DEF_BIT_STRING_constraint_size;
|
||||
}
|
||||
|
||||
if(specs->subvariant != ASN_OSUBV_BIT) {
|
||||
ASN_DEBUG("Subvariant %d is not BIT OSUBV_BIT", specs->subvariant);
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the string.
|
||||
*/
|
||||
if(!st) {
|
||||
st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
|
||||
if(!st) RETURN(RC_FAIL);
|
||||
}
|
||||
|
||||
ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
|
||||
csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
|
||||
csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
|
||||
|
||||
if(csiz->flags & APC_EXTENSIBLE) {
|
||||
int inext = per_get_few_bits(pd, 1);
|
||||
if(inext < 0) RETURN(RC_WMORE);
|
||||
if(inext) {
|
||||
csiz = &asn_DEF_BIT_STRING_constraint_size;
|
||||
}
|
||||
}
|
||||
|
||||
if(csiz->effective_bits >= 0) {
|
||||
FREEMEM(st->buf);
|
||||
st->size = (csiz->upper_bound + 7) >> 3;
|
||||
st->buf = (uint8_t *)MALLOC(st->size + 1);
|
||||
if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
|
||||
}
|
||||
|
||||
/* X.691, #16.5: zero-length encoding */
|
||||
/* X.691, #16.6: short fixed length encoding (up to 2 octets) */
|
||||
/* X.691, #16.7: long fixed length encoding (up to 64K octets) */
|
||||
if(csiz->effective_bits == 0) {
|
||||
int ret;
|
||||
ASN_DEBUG("Encoding BIT STRING size %ld", csiz->upper_bound);
|
||||
ret = per_get_many_bits(pd, st->buf, 0, csiz->upper_bound);
|
||||
if(ret < 0) RETURN(RC_WMORE);
|
||||
consumed_myself += csiz->upper_bound;
|
||||
st->buf[st->size] = 0;
|
||||
st->bits_unused = (8 - (csiz->upper_bound & 0x7)) & 0x7;
|
||||
RETURN(RC_OK);
|
||||
}
|
||||
|
||||
st->size = 0;
|
||||
do {
|
||||
ssize_t raw_len;
|
||||
ssize_t len_bytes;
|
||||
ssize_t len_bits;
|
||||
void *p;
|
||||
int ret;
|
||||
|
||||
/* Get the PER length */
|
||||
raw_len = uper_get_length(pd, csiz->effective_bits, csiz->lower_bound,
|
||||
&repeat);
|
||||
if(raw_len < 0) RETURN(RC_WMORE);
|
||||
if(raw_len == 0 && st->buf) break;
|
||||
|
||||
ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
|
||||
(long)csiz->effective_bits, (long)raw_len,
|
||||
repeat ? "repeat" : "once", td->name);
|
||||
len_bits = raw_len;
|
||||
len_bytes = (len_bits + 7) >> 3;
|
||||
if(len_bits & 0x7) st->bits_unused = 8 - (len_bits & 0x7);
|
||||
/* len_bits be multiple of 16K if repeat is set */
|
||||
p = REALLOC(st->buf, st->size + len_bytes + 1);
|
||||
if(!p) RETURN(RC_FAIL);
|
||||
st->buf = (uint8_t *)p;
|
||||
|
||||
ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits);
|
||||
if(ret < 0) RETURN(RC_WMORE);
|
||||
st->size += len_bytes;
|
||||
} while(repeat);
|
||||
st->buf[st->size] = 0; /* nul-terminate */
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
BIT_STRING_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
const asn_OCTET_STRING_specifics_t *specs =
|
||||
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
|
||||
: &asn_SPC_BIT_STRING_specs;
|
||||
const asn_per_constraints_t *pc =
|
||||
constraints ? constraints : td->encoding_constraints.per_constraints;
|
||||
const asn_per_constraint_t *csiz;
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
BIT_STRING_t compact_bstr; /* Do not modify this directly! */
|
||||
asn_enc_rval_t er = { 0, 0, 0 };
|
||||
int inext = 0; /* Lies not within extension root */
|
||||
size_t size_in_bits;
|
||||
const uint8_t *buf;
|
||||
int ret;
|
||||
int ct_extensible;
|
||||
|
||||
if(!st || (!st->buf && st->size))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
if(specs->subvariant == ASN_OSUBV_BIT) {
|
||||
if((st->size == 0 && st->bits_unused) || (st->bits_unused & ~7))
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
if(pc) {
|
||||
csiz = &pc->size;
|
||||
} else {
|
||||
csiz = &asn_DEF_BIT_STRING_constraint_size;
|
||||
}
|
||||
ct_extensible = csiz->flags & APC_EXTENSIBLE;
|
||||
|
||||
/* Figure out the size without the trailing bits */
|
||||
st = BIT_STRING__compactify(st, &compact_bstr);
|
||||
size_in_bits = 8 * st->size - st->bits_unused;
|
||||
|
||||
ASN_DEBUG(
|
||||
"Encoding %s into %" ASN_PRI_SIZE " bits"
|
||||
" (%ld..%ld, effective %d)%s",
|
||||
td->name, size_in_bits, csiz->lower_bound, csiz->upper_bound,
|
||||
csiz->effective_bits, ct_extensible ? " EXT" : "");
|
||||
|
||||
/* Figure out whether size lies within PER visible constraint */
|
||||
|
||||
if(csiz->effective_bits >= 0) {
|
||||
if((ssize_t)size_in_bits > csiz->upper_bound) {
|
||||
if(ct_extensible) {
|
||||
csiz = &asn_DEF_BIT_STRING_constraint_size;
|
||||
inext = 1;
|
||||
} else {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inext = 0;
|
||||
}
|
||||
|
||||
if(ct_extensible) {
|
||||
/* Declare whether length is [not] within extension root */
|
||||
if(per_put_few_bits(po, inext, 1))
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
if(csiz->effective_bits >= 0 && !inext) {
|
||||
int add_trailer = (ssize_t)size_in_bits < csiz->lower_bound;
|
||||
ASN_DEBUG(
|
||||
"Encoding %" ASN_PRI_SIZE " bytes (%ld), length (in %d bits) trailer %d; actual "
|
||||
"value %" ASN_PRI_SSIZE "",
|
||||
st->size, size_in_bits - csiz->lower_bound, csiz->effective_bits,
|
||||
add_trailer,
|
||||
add_trailer ? 0 : (ssize_t)size_in_bits - csiz->lower_bound);
|
||||
ret = per_put_few_bits(
|
||||
po, add_trailer ? 0 : (ssize_t)size_in_bits - csiz->lower_bound,
|
||||
csiz->effective_bits);
|
||||
if(ret) ASN__ENCODE_FAILED;
|
||||
ret = per_put_many_bits(po, st->buf, size_in_bits);
|
||||
if(ret) ASN__ENCODE_FAILED;
|
||||
if(add_trailer) {
|
||||
static const uint8_t zeros[16];
|
||||
size_t trailing_zero_bits = csiz->lower_bound - size_in_bits;
|
||||
while(trailing_zero_bits > 0) {
|
||||
if(trailing_zero_bits > 8 * sizeof(zeros)) {
|
||||
ret = per_put_many_bits(po, zeros, 8 * sizeof(zeros));
|
||||
trailing_zero_bits -= 8 * sizeof(zeros);
|
||||
} else {
|
||||
ret = per_put_many_bits(po, zeros, trailing_zero_bits);
|
||||
trailing_zero_bits = 0;
|
||||
}
|
||||
if(ret) ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
ASN_DEBUG("Encoding %" ASN_PRI_SIZE " bytes", st->size);
|
||||
|
||||
buf = st->buf;
|
||||
do {
|
||||
int need_eom = 0;
|
||||
ssize_t maySave = uper_put_length(po, size_in_bits, &need_eom);
|
||||
if(maySave < 0) ASN__ENCODE_FAILED;
|
||||
|
||||
ASN_DEBUG("Encoding %" ASN_PRI_SSIZE " of %" ASN_PRI_SIZE "", maySave, size_in_bits);
|
||||
|
||||
ret = per_put_many_bits(po, buf, maySave);
|
||||
if(ret) ASN__ENCODE_FAILED;
|
||||
|
||||
buf += maySave >> 3;
|
||||
size_in_bits -= maySave;
|
||||
assert(!(maySave & 0x07) || !size_in_bits);
|
||||
if(need_eom && uper_put_length(po, 0, 0))
|
||||
ASN__ENCODE_FAILED; /* End of Message length */
|
||||
} while(size_in_bits);
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
#endif /* ASN_DISABLE_PER_SUPPORT */
|
||||
|
||||
asn_random_fill_result_t
|
||||
BIT_STRING_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const asn_encoding_constraints_t *constraints,
|
||||
size_t max_length) {
|
||||
const asn_OCTET_STRING_specifics_t *specs =
|
||||
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
|
||||
: &asn_SPC_BIT_STRING_specs;
|
||||
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
|
||||
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
|
||||
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
|
||||
static unsigned lengths[] = {0, 1, 2, 3, 4, 8,
|
||||
126, 127, 128, 16383, 16384, 16385,
|
||||
65534, 65535, 65536, 65537};
|
||||
uint8_t *buf;
|
||||
uint8_t *bend;
|
||||
uint8_t *b;
|
||||
size_t rnd_bits, rnd_len;
|
||||
BIT_STRING_t *st;
|
||||
|
||||
if(max_length == 0) return result_skipped;
|
||||
|
||||
switch(specs->subvariant) {
|
||||
case ASN_OSUBV_ANY:
|
||||
return result_failed;
|
||||
case ASN_OSUBV_BIT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Figure out how far we should go */
|
||||
rnd_bits = lengths[asn_random_between(
|
||||
0, sizeof(lengths) / sizeof(lengths[0]) - 1)];
|
||||
if(!constraints || !constraints->per_constraints)
|
||||
constraints = &td->encoding_constraints;
|
||||
if(constraints->per_constraints) {
|
||||
const asn_per_constraint_t *pc = &constraints->per_constraints->size;
|
||||
if(pc->flags & APC_CONSTRAINED) {
|
||||
long suggested_upper_bound = pc->upper_bound < (ssize_t)max_length
|
||||
? pc->upper_bound
|
||||
: (ssize_t)max_length;
|
||||
if(max_length < (size_t)pc->lower_bound) {
|
||||
return result_skipped;
|
||||
}
|
||||
if(pc->flags & APC_EXTENSIBLE) {
|
||||
switch(asn_random_between(0, 5)) {
|
||||
case 0:
|
||||
if(pc->lower_bound > 0) {
|
||||
rnd_bits = pc->lower_bound - 1;
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
case 1:
|
||||
rnd_bits = pc->upper_bound + 1;
|
||||
break;
|
||||
case 2:
|
||||
/* Keep rnd_bits from the table */
|
||||
if(rnd_bits < max_length) {
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
rnd_bits = asn_random_between(pc->lower_bound,
|
||||
suggested_upper_bound);
|
||||
}
|
||||
} else {
|
||||
rnd_bits =
|
||||
asn_random_between(pc->lower_bound, suggested_upper_bound);
|
||||
}
|
||||
} else {
|
||||
rnd_bits = asn_random_between(0, max_length - 1);
|
||||
}
|
||||
} else if(rnd_bits >= max_length) {
|
||||
rnd_bits = asn_random_between(0, max_length - 1);
|
||||
}
|
||||
|
||||
rnd_len = (rnd_bits + 7) / 8;
|
||||
buf = CALLOC(1, rnd_len + 1);
|
||||
if(!buf) return result_failed;
|
||||
|
||||
bend = &buf[rnd_len];
|
||||
|
||||
for(b = buf; b < bend; b++) {
|
||||
*(uint8_t *)b = asn_random_between(0, 255);
|
||||
}
|
||||
*b = 0; /* Zero-terminate just in case. */
|
||||
|
||||
if(*sptr) {
|
||||
st = *sptr;
|
||||
FREEMEM(st->buf);
|
||||
} else {
|
||||
st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
|
||||
if(!st) {
|
||||
FREEMEM(buf);
|
||||
return result_failed;
|
||||
}
|
||||
}
|
||||
|
||||
st->buf = buf;
|
||||
st->size = rnd_len;
|
||||
st->bits_unused = (8 - (rnd_bits & 0x7)) & 0x7;
|
||||
if(st->bits_unused) {
|
||||
assert(st->size > 0);
|
||||
st->buf[st->size-1] &= 0xff << st->bits_unused;
|
||||
}
|
||||
|
||||
result_ok.length = st->size;
|
||||
return result_ok;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _BIT_STRING_H_
|
||||
#define _BIT_STRING_H_
|
||||
|
||||
#include <OCTET_STRING.h> /* Some help from OCTET STRING */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct BIT_STRING_s {
|
||||
uint8_t *buf; /* BIT STRING body */
|
||||
size_t size; /* Size of the above buffer */
|
||||
|
||||
int bits_unused;/* Unused trailing bits in the last octet (0..7) */
|
||||
|
||||
asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */
|
||||
} BIT_STRING_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_BIT_STRING;
|
||||
extern asn_TYPE_operation_t asn_OP_BIT_STRING;
|
||||
extern asn_OCTET_STRING_specifics_t asn_SPC_BIT_STRING_specs;
|
||||
|
||||
asn_struct_print_f BIT_STRING_print; /* Human-readable output */
|
||||
asn_struct_compare_f BIT_STRING_compare;
|
||||
asn_constr_check_f BIT_STRING_constraint;
|
||||
xer_type_encoder_f BIT_STRING_encode_xer;
|
||||
oer_type_decoder_f BIT_STRING_decode_oer;
|
||||
oer_type_encoder_f BIT_STRING_encode_oer;
|
||||
per_type_decoder_f BIT_STRING_decode_uper;
|
||||
per_type_encoder_f BIT_STRING_encode_uper;
|
||||
asn_random_fill_f BIT_STRING_random_fill;
|
||||
|
||||
#define BIT_STRING_free OCTET_STRING_free
|
||||
#define BIT_STRING_decode_ber OCTET_STRING_decode_ber
|
||||
#define BIT_STRING_encode_der OCTET_STRING_encode_der
|
||||
#define BIT_STRING_decode_xer OCTET_STRING_decode_xer_binary
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BIT_STRING_H_ */
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_DISABLE_OER_SUPPORT
|
||||
|
||||
#include <asn_internal.h>
|
||||
#include <BIT_STRING.h>
|
||||
#include <errno.h>
|
||||
|
||||
asn_dec_rval_t
|
||||
BIT_STRING_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, void **sptr,
|
||||
const void *ptr, size_t size) {
|
||||
BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
|
||||
const asn_oer_constraints_t *cts =
|
||||
constraints ? constraints : td->encoding_constraints.oer_constraints;
|
||||
ssize_t ct_size = cts ? cts->size : -1;
|
||||
asn_dec_rval_t rval = {RC_OK, 0};
|
||||
size_t expected_length = 0;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
|
||||
if(!st) {
|
||||
st = (BIT_STRING_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
if(ct_size >= 0) {
|
||||
expected_length = (ct_size + 7) >> 3;
|
||||
st->bits_unused = (8 - (ct_size & 7)) & 7;
|
||||
} else {
|
||||
/*
|
||||
* X.696 (08/2015) #13.3.1
|
||||
* Encode length determinant as _number of octets_, but only
|
||||
* if upper bound is not equal to lower bound.
|
||||
*/
|
||||
ssize_t len_len = oer_fetch_length(ptr, size, &expected_length);
|
||||
if(len_len > 0) {
|
||||
ptr = (const char *)ptr + len_len;
|
||||
size -= len_len;
|
||||
} else if(len_len == 0) {
|
||||
ASN__DECODE_STARVED;
|
||||
} else if(len_len < 0) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
if(expected_length < 1) {
|
||||
ASN__DECODE_FAILED;
|
||||
} else if(expected_length > size) {
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
|
||||
st->bits_unused = ((const uint8_t *)ptr)[0];
|
||||
if(st->bits_unused & ~7) {
|
||||
ASN_DEBUG("%s: unused bits outside of 0..7 range", td->name);
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
ptr = (const char *)ptr + 1;
|
||||
size--;
|
||||
expected_length--;
|
||||
rval.consumed = len_len + 1;
|
||||
}
|
||||
|
||||
if(size < expected_length) {
|
||||
ASN__DECODE_STARVED;
|
||||
} else {
|
||||
uint8_t *buf = MALLOC(expected_length + 1);
|
||||
if(buf == NULL) {
|
||||
ASN__DECODE_FAILED;
|
||||
} else {
|
||||
memcpy(buf, ptr, expected_length);
|
||||
buf[expected_length] = '\0';
|
||||
}
|
||||
FREEMEM(st->buf);
|
||||
st->buf = buf;
|
||||
st->size = expected_length;
|
||||
if(expected_length > 0) {
|
||||
buf[expected_length - 1] &= (0xff << st->bits_unused);
|
||||
}
|
||||
|
||||
rval.consumed += expected_length;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode as Canonical OER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
BIT_STRING_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
const void *sptr, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
|
||||
asn_enc_rval_t erval = {0, 0, 0};
|
||||
const asn_oer_constraints_t *cts =
|
||||
constraints ? constraints : td->encoding_constraints.oer_constraints;
|
||||
ssize_t ct_size = cts ? cts->size : -1;
|
||||
size_t trailing_zeros = 0;
|
||||
int fix_last_byte = 0;
|
||||
|
||||
if(!st) ASN__ENCODE_FAILED;
|
||||
|
||||
if(st->bits_unused & ~7) {
|
||||
ASN_DEBUG("BIT STRING unused bits %d out of 0..7 range",
|
||||
st->bits_unused);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
if(st->bits_unused && !(st->size && st->buf)) {
|
||||
ASN_DEBUG("BIT STRING %s size 0 can't support unused bits %d", td->name,
|
||||
st->bits_unused);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
if(ct_size >= 0) {
|
||||
size_t ct_bytes = (ct_size + 7) >> 3;
|
||||
if(st->size > ct_bytes) {
|
||||
ASN_DEBUG("More bits in BIT STRING %s (%" ASN_PRI_SSIZE ") than constrained %" ASN_PRI_SSIZE "",
|
||||
td->name, 8 * st->size - st->bits_unused, ct_size);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
trailing_zeros = ct_bytes - st->size; /* Allow larger constraint */
|
||||
} else {
|
||||
uint8_t ub = st->bits_unused & 7;
|
||||
ssize_t len_len = oer_serialize_length(1 + st->size, cb, app_key);
|
||||
if(len_len < 0) ASN__ENCODE_FAILED;
|
||||
if(cb(&ub, 1, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
erval.encoded += len_len + 1;
|
||||
}
|
||||
|
||||
if(st->bits_unused) {
|
||||
if(st->buf[st->size - 1] & (0xff << st->bits_unused)) {
|
||||
fix_last_byte = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(cb(st->buf, st->size - fix_last_byte, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
if(fix_last_byte) {
|
||||
uint8_t b = st->buf[st->size - 1] & (0xff << st->bits_unused);
|
||||
if(cb(&b, 1, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
erval.encoded += st->size;
|
||||
|
||||
if(trailing_zeros) {
|
||||
static uint8_t zeros[16];
|
||||
while(trailing_zeros > 0) {
|
||||
int ret;
|
||||
if(trailing_zeros < sizeof(zeros)) {
|
||||
ret = cb(zeros, trailing_zeros, app_key);
|
||||
erval.encoded += trailing_zeros;
|
||||
} else {
|
||||
ret = cb(zeros, sizeof(zeros), app_key);
|
||||
erval.encoded += sizeof(zeros);
|
||||
}
|
||||
if(ret < 0) ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return erval;
|
||||
}
|
||||
|
||||
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "CardDetails.h"
|
||||
|
||||
asn_TYPE_member_t asn_MBR_CardDetails_1[] = {
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct CardDetails, protocol),
|
||||
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_Protocol,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"protocol"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct CardDetails, csn),
|
||||
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_OCTET_STRING,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"csn"
|
||||
},
|
||||
{ ATF_POINTER, 2, offsetof(struct CardDetails, atqa),
|
||||
(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_OCTET_STRING,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"atqa"
|
||||
},
|
||||
{ ATF_POINTER, 1, offsetof(struct CardDetails, sak),
|
||||
(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_OCTET_STRING,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"sak"
|
||||
},
|
||||
};
|
||||
static const int asn_MAP_CardDetails_oms_1[] = { 2, 3 };
|
||||
static const ber_tlv_tag_t asn_DEF_CardDetails_tags_1[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
|
||||
};
|
||||
static const asn_TYPE_tag2member_t asn_MAP_CardDetails_tag2el_1[] = {
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* protocol */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* csn */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 }, /* atqa */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 3, 0, 0 } /* sak */
|
||||
};
|
||||
asn_SEQUENCE_specifics_t asn_SPC_CardDetails_specs_1 = {
|
||||
sizeof(struct CardDetails),
|
||||
offsetof(struct CardDetails, _asn_ctx),
|
||||
asn_MAP_CardDetails_tag2el_1,
|
||||
4, /* Count of tags in the map */
|
||||
asn_MAP_CardDetails_oms_1, /* Optional members */
|
||||
2, 0, /* Root/Additions */
|
||||
-1, /* First extension addition */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_CardDetails = {
|
||||
"CardDetails",
|
||||
"CardDetails",
|
||||
&asn_OP_SEQUENCE,
|
||||
asn_DEF_CardDetails_tags_1,
|
||||
sizeof(asn_DEF_CardDetails_tags_1)
|
||||
/sizeof(asn_DEF_CardDetails_tags_1[0]), /* 1 */
|
||||
asn_DEF_CardDetails_tags_1, /* Same as above */
|
||||
sizeof(asn_DEF_CardDetails_tags_1)
|
||||
/sizeof(asn_DEF_CardDetails_tags_1[0]), /* 1 */
|
||||
{ 0, 0, SEQUENCE_constraint },
|
||||
asn_MBR_CardDetails_1,
|
||||
4, /* Elements count */
|
||||
&asn_SPC_CardDetails_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _CardDetails_H_
|
||||
#define _CardDetails_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include "Protocol.h"
|
||||
#include <OCTET_STRING.h>
|
||||
#include <constr_SEQUENCE.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* CardDetails */
|
||||
typedef struct CardDetails {
|
||||
Protocol_t protocol;
|
||||
OCTET_STRING_t csn;
|
||||
OCTET_STRING_t *atqa /* OPTIONAL */;
|
||||
OCTET_STRING_t *sak /* OPTIONAL */;
|
||||
|
||||
/* Context for parsing across buffer boundaries */
|
||||
asn_struct_ctx_t _asn_ctx;
|
||||
} CardDetails_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_CardDetails;
|
||||
extern asn_SEQUENCE_specifics_t asn_SPC_CardDetails_specs_1;
|
||||
extern asn_TYPE_member_t asn_MBR_CardDetails_1[4];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CardDetails_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "CardDetected.h"
|
||||
|
||||
asn_TYPE_member_t asn_MBR_CardDetected_1[] = {
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct CardDetected, detectedCardDetails),
|
||||
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_CardDetails,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"detectedCardDetails"
|
||||
},
|
||||
};
|
||||
static const ber_tlv_tag_t asn_DEF_CardDetected_tags_1[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
|
||||
};
|
||||
static const asn_TYPE_tag2member_t asn_MAP_CardDetected_tag2el_1[] = {
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* detectedCardDetails */
|
||||
};
|
||||
asn_SEQUENCE_specifics_t asn_SPC_CardDetected_specs_1 = {
|
||||
sizeof(struct CardDetected),
|
||||
offsetof(struct CardDetected, _asn_ctx),
|
||||
asn_MAP_CardDetected_tag2el_1,
|
||||
1, /* Count of tags in the map */
|
||||
0, 0, 0, /* Optional elements (not needed) */
|
||||
-1, /* First extension addition */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_CardDetected = {
|
||||
"CardDetected",
|
||||
"CardDetected",
|
||||
&asn_OP_SEQUENCE,
|
||||
asn_DEF_CardDetected_tags_1,
|
||||
sizeof(asn_DEF_CardDetected_tags_1)
|
||||
/sizeof(asn_DEF_CardDetected_tags_1[0]), /* 1 */
|
||||
asn_DEF_CardDetected_tags_1, /* Same as above */
|
||||
sizeof(asn_DEF_CardDetected_tags_1)
|
||||
/sizeof(asn_DEF_CardDetected_tags_1[0]), /* 1 */
|
||||
{ 0, 0, SEQUENCE_constraint },
|
||||
asn_MBR_CardDetected_1,
|
||||
1, /* Elements count */
|
||||
&asn_SPC_CardDetected_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _CardDetected_H_
|
||||
#define _CardDetected_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include "CardDetails.h"
|
||||
#include <constr_SEQUENCE.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* CardDetected */
|
||||
typedef struct CardDetected {
|
||||
CardDetails_t detectedCardDetails;
|
||||
|
||||
/* Context for parsing across buffer boundaries */
|
||||
asn_struct_ctx_t _asn_ctx;
|
||||
} CardDetected_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_CardDetected;
|
||||
extern asn_SEQUENCE_specifics_t asn_SPC_CardDetected_specs_1;
|
||||
extern asn_TYPE_member_t asn_MBR_CardDetected_1[1];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CardDetected_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "ContentElementTag.h"
|
||||
|
||||
/*
|
||||
* This type is implemented using NativeEnumerated,
|
||||
* so here we adjust the DEF accordingly.
|
||||
*/
|
||||
static asn_oer_constraints_t asn_OER_type_ContentElementTag_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
-1};
|
||||
asn_per_constraints_t asn_PER_type_ContentElementTag_constr_1 CC_NOTUSED = {
|
||||
{ APC_CONSTRAINED, 0, 0, 0, 0 } /* (0..0) */,
|
||||
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
|
||||
0, 0 /* No PER value map */
|
||||
};
|
||||
static const asn_INTEGER_enum_map_t asn_MAP_ContentElementTag_value2enum_1[] = {
|
||||
{ 4, 32, "implicitFormatPhysicalAccessBits" }
|
||||
};
|
||||
static const unsigned int asn_MAP_ContentElementTag_enum2value_1[] = {
|
||||
0 /* implicitFormatPhysicalAccessBits(4) */
|
||||
};
|
||||
const asn_INTEGER_specifics_t asn_SPC_ContentElementTag_specs_1 = {
|
||||
asn_MAP_ContentElementTag_value2enum_1, /* "tag" => N; sorted by tag */
|
||||
asn_MAP_ContentElementTag_enum2value_1, /* N => "tag"; sorted by N */
|
||||
1, /* Number of elements in the maps */
|
||||
0, /* Enumeration is not extensible */
|
||||
1, /* Strict enumeration */
|
||||
0, /* Native long size */
|
||||
0
|
||||
};
|
||||
static const ber_tlv_tag_t asn_DEF_ContentElementTag_tags_1[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_ContentElementTag = {
|
||||
"ContentElementTag",
|
||||
"ContentElementTag",
|
||||
&asn_OP_NativeEnumerated,
|
||||
asn_DEF_ContentElementTag_tags_1,
|
||||
sizeof(asn_DEF_ContentElementTag_tags_1)
|
||||
/sizeof(asn_DEF_ContentElementTag_tags_1[0]), /* 1 */
|
||||
asn_DEF_ContentElementTag_tags_1, /* Same as above */
|
||||
sizeof(asn_DEF_ContentElementTag_tags_1)
|
||||
/sizeof(asn_DEF_ContentElementTag_tags_1[0]), /* 1 */
|
||||
{ &asn_OER_type_ContentElementTag_constr_1, &asn_PER_type_ContentElementTag_constr_1, NativeEnumerated_constraint },
|
||||
0, 0, /* Defined elsewhere */
|
||||
&asn_SPC_ContentElementTag_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _ContentElementTag_H_
|
||||
#define _ContentElementTag_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include <NativeEnumerated.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Dependencies */
|
||||
typedef enum ContentElementTag {
|
||||
ContentElementTag_implicitFormatPhysicalAccessBits = 4
|
||||
} e_ContentElementTag;
|
||||
|
||||
/* ContentElementTag */
|
||||
typedef long ContentElementTag_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_per_constraints_t asn_PER_type_ContentElementTag_constr_1;
|
||||
extern asn_TYPE_descriptor_t asn_DEF_ContentElementTag;
|
||||
extern const asn_INTEGER_specifics_t asn_SPC_ContentElementTag_specs_1;
|
||||
asn_struct_free_f ContentElementTag_free;
|
||||
asn_struct_print_f ContentElementTag_print;
|
||||
asn_constr_check_f ContentElementTag_constraint;
|
||||
ber_type_decoder_f ContentElementTag_decode_ber;
|
||||
der_type_encoder_f ContentElementTag_encode_der;
|
||||
xer_type_decoder_f ContentElementTag_decode_xer;
|
||||
xer_type_encoder_f ContentElementTag_encode_xer;
|
||||
oer_type_decoder_f ContentElementTag_decode_oer;
|
||||
oer_type_encoder_f ContentElementTag_encode_oer;
|
||||
per_type_decoder_f ContentElementTag_decode_uper;
|
||||
per_type_encoder_f ContentElementTag_encode_uper;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ContentElementTag_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "ErrorResponse.h"
|
||||
|
||||
asn_TYPE_member_t asn_MBR_ErrorResponse_1[] = {
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct ErrorResponse, errorCode),
|
||||
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_NativeInteger,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"errorCode"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct ErrorResponse, data),
|
||||
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_OCTET_STRING,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"data"
|
||||
},
|
||||
};
|
||||
static const ber_tlv_tag_t asn_DEF_ErrorResponse_tags_1[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
|
||||
};
|
||||
static const asn_TYPE_tag2member_t asn_MAP_ErrorResponse_tag2el_1[] = {
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* errorCode */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* data */
|
||||
};
|
||||
asn_SEQUENCE_specifics_t asn_SPC_ErrorResponse_specs_1 = {
|
||||
sizeof(struct ErrorResponse),
|
||||
offsetof(struct ErrorResponse, _asn_ctx),
|
||||
asn_MAP_ErrorResponse_tag2el_1,
|
||||
2, /* Count of tags in the map */
|
||||
0, 0, 0, /* Optional elements (not needed) */
|
||||
-1, /* First extension addition */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_ErrorResponse = {
|
||||
"ErrorResponse",
|
||||
"ErrorResponse",
|
||||
&asn_OP_SEQUENCE,
|
||||
asn_DEF_ErrorResponse_tags_1,
|
||||
sizeof(asn_DEF_ErrorResponse_tags_1)
|
||||
/sizeof(asn_DEF_ErrorResponse_tags_1[0]), /* 1 */
|
||||
asn_DEF_ErrorResponse_tags_1, /* Same as above */
|
||||
sizeof(asn_DEF_ErrorResponse_tags_1)
|
||||
/sizeof(asn_DEF_ErrorResponse_tags_1[0]), /* 1 */
|
||||
{ 0, 0, SEQUENCE_constraint },
|
||||
asn_MBR_ErrorResponse_1,
|
||||
2, /* Elements count */
|
||||
&asn_SPC_ErrorResponse_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _ErrorResponse_H_
|
||||
#define _ErrorResponse_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include <NativeInteger.h>
|
||||
#include <OCTET_STRING.h>
|
||||
#include <constr_SEQUENCE.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ErrorResponse */
|
||||
typedef struct ErrorResponse {
|
||||
long errorCode;
|
||||
OCTET_STRING_t data;
|
||||
|
||||
/* Context for parsing across buffer boundaries */
|
||||
asn_struct_ctx_t _asn_ctx;
|
||||
} ErrorResponse_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_ErrorResponse;
|
||||
extern asn_SEQUENCE_specifics_t asn_SPC_ErrorResponse_specs_1;
|
||||
extern asn_TYPE_member_t asn_MBR_ErrorResponse_1[2];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ErrorResponse_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "FrameProtocol.h"
|
||||
|
||||
/*
|
||||
* This type is implemented using NativeEnumerated,
|
||||
* so here we adjust the DEF accordingly.
|
||||
*/
|
||||
static asn_oer_constraints_t asn_OER_type_FrameProtocol_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
-1};
|
||||
static asn_per_constraints_t asn_PER_type_FrameProtocol_constr_1 CC_NOTUSED = {
|
||||
{ APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */,
|
||||
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
|
||||
0, 0 /* No PER value map */
|
||||
};
|
||||
static const asn_INTEGER_enum_map_t asn_MAP_FrameProtocol_value2enum_1[] = {
|
||||
{ 2, 3, "nfc" },
|
||||
{ 4, 6, "iclass" }
|
||||
};
|
||||
static const unsigned int asn_MAP_FrameProtocol_enum2value_1[] = {
|
||||
1, /* iclass(4) */
|
||||
0 /* nfc(2) */
|
||||
};
|
||||
static const asn_INTEGER_specifics_t asn_SPC_FrameProtocol_specs_1 = {
|
||||
asn_MAP_FrameProtocol_value2enum_1, /* "tag" => N; sorted by tag */
|
||||
asn_MAP_FrameProtocol_enum2value_1, /* N => "tag"; sorted by N */
|
||||
2, /* Number of elements in the maps */
|
||||
0, /* Enumeration is not extensible */
|
||||
1, /* Strict enumeration */
|
||||
0, /* Native long size */
|
||||
0
|
||||
};
|
||||
static const ber_tlv_tag_t asn_DEF_FrameProtocol_tags_1[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_FrameProtocol = {
|
||||
"FrameProtocol",
|
||||
"FrameProtocol",
|
||||
&asn_OP_NativeEnumerated,
|
||||
asn_DEF_FrameProtocol_tags_1,
|
||||
sizeof(asn_DEF_FrameProtocol_tags_1)
|
||||
/sizeof(asn_DEF_FrameProtocol_tags_1[0]), /* 1 */
|
||||
asn_DEF_FrameProtocol_tags_1, /* Same as above */
|
||||
sizeof(asn_DEF_FrameProtocol_tags_1)
|
||||
/sizeof(asn_DEF_FrameProtocol_tags_1[0]), /* 1 */
|
||||
{ &asn_OER_type_FrameProtocol_constr_1, &asn_PER_type_FrameProtocol_constr_1, NativeEnumerated_constraint },
|
||||
0, 0, /* Defined elsewhere */
|
||||
&asn_SPC_FrameProtocol_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _FrameProtocol_H_
|
||||
#define _FrameProtocol_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include <NativeEnumerated.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Dependencies */
|
||||
typedef enum FrameProtocol {
|
||||
FrameProtocol_nfc = 2,
|
||||
FrameProtocol_iclass = 4
|
||||
} e_FrameProtocol;
|
||||
|
||||
/* FrameProtocol */
|
||||
typedef long FrameProtocol_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_FrameProtocol;
|
||||
asn_struct_free_f FrameProtocol_free;
|
||||
asn_struct_print_f FrameProtocol_print;
|
||||
asn_constr_check_f FrameProtocol_constraint;
|
||||
ber_type_decoder_f FrameProtocol_decode_ber;
|
||||
der_type_encoder_f FrameProtocol_encode_der;
|
||||
xer_type_decoder_f FrameProtocol_decode_xer;
|
||||
xer_type_encoder_f FrameProtocol_encode_xer;
|
||||
oer_type_decoder_f FrameProtocol_decode_oer;
|
||||
oer_type_encoder_f FrameProtocol_encode_oer;
|
||||
per_type_decoder_f FrameProtocol_decode_uper;
|
||||
per_type_encoder_f FrameProtocol_encode_uper;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FrameProtocol_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,104 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _INTEGER_H_
|
||||
#define _INTEGER_H_
|
||||
|
||||
#include <asn_application.h>
|
||||
#include <asn_codecs_prim.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef ASN__PRIMITIVE_TYPE_t INTEGER_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_INTEGER;
|
||||
extern asn_TYPE_operation_t asn_OP_INTEGER;
|
||||
|
||||
/* Map with <tag> to integer value association */
|
||||
typedef struct asn_INTEGER_enum_map_s {
|
||||
long nat_value; /* associated native integer value */
|
||||
size_t enum_len; /* strlen("tag") */
|
||||
const char *enum_name; /* "tag" */
|
||||
} asn_INTEGER_enum_map_t;
|
||||
|
||||
/* This type describes an enumeration for INTEGER and ENUMERATED types */
|
||||
typedef struct asn_INTEGER_specifics_s {
|
||||
const asn_INTEGER_enum_map_t *value2enum; /* N -> "tag"; sorted by N */
|
||||
const unsigned int *enum2value; /* "tag" => N; sorted by tag */
|
||||
int map_count; /* Elements in either map */
|
||||
int extension; /* This map is extensible */
|
||||
int strict_enumeration; /* Enumeration set is fixed */
|
||||
int field_width; /* Size of native integer */
|
||||
int field_unsigned; /* Signed=0, unsigned=1 */
|
||||
} asn_INTEGER_specifics_t;
|
||||
|
||||
#define INTEGER_free ASN__PRIMITIVE_TYPE_free
|
||||
#define INTEGER_decode_ber ber_decode_primitive
|
||||
#define INTEGER_constraint asn_generic_no_constraint
|
||||
asn_struct_print_f INTEGER_print;
|
||||
asn_struct_compare_f INTEGER_compare;
|
||||
der_type_encoder_f INTEGER_encode_der;
|
||||
xer_type_decoder_f INTEGER_decode_xer;
|
||||
xer_type_encoder_f INTEGER_encode_xer;
|
||||
oer_type_decoder_f INTEGER_decode_oer;
|
||||
oer_type_encoder_f INTEGER_encode_oer;
|
||||
per_type_decoder_f INTEGER_decode_uper;
|
||||
per_type_encoder_f INTEGER_encode_uper;
|
||||
asn_random_fill_f INTEGER_random_fill;
|
||||
|
||||
/***********************************
|
||||
* Some handy conversion routines. *
|
||||
***********************************/
|
||||
|
||||
/*
|
||||
* Natiwe size-independent conversion of native integers to/from INTEGER.
|
||||
* (l_size) is in bytes.
|
||||
* Returns 0 if it was possible to convert, -1 otherwise.
|
||||
* -1/EINVAL: Mandatory argument missing
|
||||
* -1/ERANGE: Value encoded is out of range for long representation
|
||||
* -1/ENOMEM: Memory allocation failed (in asn_*2INTEGER()).
|
||||
*/
|
||||
int asn_INTEGER2imax(const INTEGER_t *i, intmax_t *l);
|
||||
int asn_INTEGER2umax(const INTEGER_t *i, uintmax_t *l);
|
||||
int asn_imax2INTEGER(INTEGER_t *i, intmax_t l);
|
||||
int asn_umax2INTEGER(INTEGER_t *i, uintmax_t l);
|
||||
|
||||
/*
|
||||
* Size-specific conversion helpers.
|
||||
*/
|
||||
int asn_INTEGER2long(const INTEGER_t *i, long *l);
|
||||
int asn_INTEGER2ulong(const INTEGER_t *i, unsigned long *l);
|
||||
int asn_long2INTEGER(INTEGER_t *i, long l);
|
||||
int asn_ulong2INTEGER(INTEGER_t *i, unsigned long l);
|
||||
|
||||
/* A version of strtol/strtoimax(3) with nicer error reporting. */
|
||||
enum asn_strtox_result_e {
|
||||
ASN_STRTOX_ERROR_RANGE = -3, /* Input outside of supported numeric range */
|
||||
ASN_STRTOX_ERROR_INVAL = -2, /* Invalid data encountered (e.g., "+-") */
|
||||
ASN_STRTOX_EXPECT_MORE = -1, /* More data expected (e.g. "+") */
|
||||
ASN_STRTOX_OK = 0, /* Conversion succeded, number ends at (*end) */
|
||||
ASN_STRTOX_EXTRA_DATA = 1 /* Conversion succeded, but the string has extra stuff */
|
||||
};
|
||||
enum asn_strtox_result_e asn_strtol_lim(const char *str, const char **end,
|
||||
long *l);
|
||||
enum asn_strtox_result_e asn_strtoul_lim(const char *str, const char **end,
|
||||
unsigned long *l);
|
||||
enum asn_strtox_result_e asn_strtoimax_lim(const char *str, const char **end,
|
||||
intmax_t *l);
|
||||
enum asn_strtox_result_e asn_strtoumax_lim(const char *str, const char **end,
|
||||
uintmax_t *l);
|
||||
|
||||
/*
|
||||
* Convert the integer value into the corresponding enumeration map entry.
|
||||
*/
|
||||
const asn_INTEGER_enum_map_t *INTEGER_map_value2enum(
|
||||
const asn_INTEGER_specifics_t *specs, long value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _INTEGER_H_ */
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_DISABLE_OER_SUPPORT
|
||||
|
||||
#include <asn_internal.h>
|
||||
#include <INTEGER.h>
|
||||
#include <errno.h>
|
||||
|
||||
asn_dec_rval_t
|
||||
INTEGER_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, void **sptr,
|
||||
const void *ptr, size_t size) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval = {RC_OK, 0};
|
||||
INTEGER_t *st = (INTEGER_t *)*sptr;
|
||||
struct asn_oer_constraint_number_s ct = {0, 0};
|
||||
size_t req_bytes;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)specs;
|
||||
|
||||
if(!st) {
|
||||
st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
FREEMEM(st->buf);
|
||||
st->buf = 0;
|
||||
st->size = 0;
|
||||
|
||||
if(!constraints) constraints = td->encoding_constraints.oer_constraints;
|
||||
if(constraints) ct = constraints->value;
|
||||
|
||||
if(ct.width) {
|
||||
req_bytes = ct.width;
|
||||
} else {
|
||||
/* No lower bound and no upper bound, effectively */
|
||||
|
||||
ssize_t consumed = oer_fetch_length(ptr, size, &req_bytes);
|
||||
if(consumed == 0) {
|
||||
ASN__DECODE_STARVED;
|
||||
} else if(consumed == -1) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
rval.consumed += consumed;
|
||||
ptr = (const char *)ptr + consumed;
|
||||
size -= consumed;
|
||||
}
|
||||
|
||||
if(req_bytes > size) {
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
|
||||
if(ct.positive) {
|
||||
/* X.969 08/2015 10.2(a) */
|
||||
unsigned msb; /* Most significant bit */
|
||||
size_t useful_size;
|
||||
|
||||
/* Check most significant bit */
|
||||
msb = *(const uint8_t *)ptr >> 7; /* yields 0 or 1 */
|
||||
useful_size = msb + req_bytes;
|
||||
st->buf = (uint8_t *)MALLOC(useful_size + 1);
|
||||
if(!st->buf) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Record a large unsigned in a way not to confuse it
|
||||
* with signed value.
|
||||
*/
|
||||
st->buf[0] = '\0';
|
||||
memcpy(st->buf + msb, ptr, req_bytes);
|
||||
st->buf[useful_size] = '\0'; /* Just in case, 0-terminate */
|
||||
st->size = useful_size;
|
||||
|
||||
rval.consumed += req_bytes;
|
||||
return rval;
|
||||
} else {
|
||||
/* X.969 08/2015 10.2(b) */
|
||||
st->buf = (uint8_t *)MALLOC(req_bytes + 1);
|
||||
if(!st->buf) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memcpy(st->buf, ptr, req_bytes);
|
||||
st->buf[req_bytes] = '\0'; /* Just in case, 0-terminate */
|
||||
st->size = req_bytes;
|
||||
|
||||
rval.consumed += req_bytes;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode as Canonical OER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
INTEGER_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, const void *sptr,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const INTEGER_t *st = sptr;
|
||||
asn_enc_rval_t er;
|
||||
struct asn_oer_constraint_number_s ct = {0, 0};
|
||||
const uint8_t *buf;
|
||||
const uint8_t *end;
|
||||
size_t useful_bytes;
|
||||
size_t req_bytes = 0;
|
||||
int sign = 0;
|
||||
|
||||
if(!st || st->size == 0) ASN__ENCODE_FAILED;
|
||||
|
||||
if(!constraints) constraints = td->encoding_constraints.oer_constraints;
|
||||
if(constraints) ct = constraints->value;
|
||||
|
||||
er.encoded = 0;
|
||||
|
||||
buf = st->buf;
|
||||
end = buf + st->size;
|
||||
|
||||
sign = (buf && buf < end) ? buf[0] & 0x80 : 0;
|
||||
|
||||
/* Ignore 9 leading zeroes or ones */
|
||||
if(ct.positive) {
|
||||
if(sign) {
|
||||
/* The value given is a signed value. Can't proceed. */
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
/* Remove leading zeros. */
|
||||
for(; buf + 1 < end; buf++) {
|
||||
if(buf[0] != 0x0) break;
|
||||
}
|
||||
} else {
|
||||
for(; buf + 1 < end; buf++) {
|
||||
if(buf[0] == 0x0 && (buf[1] & 0x80) == 0) {
|
||||
continue;
|
||||
} else if(buf[0] == 0xff && (buf[1] & 0x80) != 0) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
useful_bytes = end - buf;
|
||||
if(ct.width) {
|
||||
req_bytes = ct.width;
|
||||
} else {
|
||||
ssize_t r = oer_serialize_length(useful_bytes, cb, app_key);
|
||||
if(r < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
er.encoded += r;
|
||||
req_bytes = useful_bytes;
|
||||
}
|
||||
|
||||
if(req_bytes < useful_bytes) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
er.encoded += req_bytes;
|
||||
|
||||
for(; req_bytes > useful_bytes; req_bytes--) {
|
||||
if(cb(sign?"\xff":"\0", 1, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if(cb(buf, useful_bytes, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "NFCCommand.h"
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_NFCCommand_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
-1};
|
||||
asn_per_constraints_t asn_PER_type_NFCCommand_constr_1 CC_NOTUSED = {
|
||||
{ APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */,
|
||||
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
|
||||
0, 0 /* No PER value map */
|
||||
};
|
||||
asn_TYPE_member_t asn_MBR_NFCCommand_1[] = {
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct NFCCommand, choice.nfcSend),
|
||||
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_NFCSend,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"nfcSend"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct NFCCommand, choice.nfcOff),
|
||||
(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_NULL,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"nfcOff"
|
||||
},
|
||||
};
|
||||
static const asn_TYPE_tag2member_t asn_MAP_NFCCommand_tag2el_1[] = {
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 0 }, /* nfcSend */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, 0, 0 } /* nfcOff */
|
||||
};
|
||||
asn_CHOICE_specifics_t asn_SPC_NFCCommand_specs_1 = {
|
||||
sizeof(struct NFCCommand),
|
||||
offsetof(struct NFCCommand, _asn_ctx),
|
||||
offsetof(struct NFCCommand, present),
|
||||
sizeof(((struct NFCCommand *)0)->present),
|
||||
asn_MAP_NFCCommand_tag2el_1,
|
||||
2, /* Count of tags in the map */
|
||||
0, 0,
|
||||
-1 /* Extensions start */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_NFCCommand = {
|
||||
"NFCCommand",
|
||||
"NFCCommand",
|
||||
&asn_OP_CHOICE,
|
||||
0, /* No effective tags (pointer) */
|
||||
0, /* No effective tags (count) */
|
||||
0, /* No tags (pointer) */
|
||||
0, /* No tags (count) */
|
||||
{ &asn_OER_type_NFCCommand_constr_1, &asn_PER_type_NFCCommand_constr_1, CHOICE_constraint },
|
||||
asn_MBR_NFCCommand_1,
|
||||
2, /* Elements count */
|
||||
&asn_SPC_NFCCommand_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _NFCCommand_H_
|
||||
#define _NFCCommand_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include "NFCSend.h"
|
||||
#include <NULL.h>
|
||||
#include <constr_CHOICE.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Dependencies */
|
||||
typedef enum NFCCommand_PR {
|
||||
NFCCommand_PR_NOTHING, /* No components present */
|
||||
NFCCommand_PR_nfcSend,
|
||||
NFCCommand_PR_nfcOff
|
||||
} NFCCommand_PR;
|
||||
|
||||
/* NFCCommand */
|
||||
typedef struct NFCCommand {
|
||||
NFCCommand_PR present;
|
||||
union NFCCommand_u {
|
||||
NFCSend_t nfcSend;
|
||||
NULL_t nfcOff;
|
||||
} choice;
|
||||
|
||||
/* Context for parsing across buffer boundaries */
|
||||
asn_struct_ctx_t _asn_ctx;
|
||||
} NFCCommand_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_NFCCommand;
|
||||
extern asn_CHOICE_specifics_t asn_SPC_NFCCommand_specs_1;
|
||||
extern asn_TYPE_member_t asn_MBR_NFCCommand_1[2];
|
||||
extern asn_per_constraints_t asn_PER_type_NFCCommand_constr_1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NFCCommand_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "NFCResponse.h"
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_NFCResponse_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
-1};
|
||||
asn_per_constraints_t asn_PER_type_NFCResponse_constr_1 CC_NOTUSED = {
|
||||
{ APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */,
|
||||
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
|
||||
0, 0 /* No PER value map */
|
||||
};
|
||||
asn_TYPE_member_t asn_MBR_NFCResponse_1[] = {
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct NFCResponse, choice.nfcRx),
|
||||
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_NFCRx,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"nfcRx"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct NFCResponse, choice.nfcAck),
|
||||
(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_NULL,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"nfcAck"
|
||||
},
|
||||
};
|
||||
static const asn_TYPE_tag2member_t asn_MAP_NFCResponse_tag2el_1[] = {
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* nfcRx */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, 0, 0 } /* nfcAck */
|
||||
};
|
||||
asn_CHOICE_specifics_t asn_SPC_NFCResponse_specs_1 = {
|
||||
sizeof(struct NFCResponse),
|
||||
offsetof(struct NFCResponse, _asn_ctx),
|
||||
offsetof(struct NFCResponse, present),
|
||||
sizeof(((struct NFCResponse *)0)->present),
|
||||
asn_MAP_NFCResponse_tag2el_1,
|
||||
2, /* Count of tags in the map */
|
||||
0, 0,
|
||||
-1 /* Extensions start */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_NFCResponse = {
|
||||
"NFCResponse",
|
||||
"NFCResponse",
|
||||
&asn_OP_CHOICE,
|
||||
0, /* No effective tags (pointer) */
|
||||
0, /* No effective tags (count) */
|
||||
0, /* No tags (pointer) */
|
||||
0, /* No tags (count) */
|
||||
{ &asn_OER_type_NFCResponse_constr_1, &asn_PER_type_NFCResponse_constr_1, CHOICE_constraint },
|
||||
asn_MBR_NFCResponse_1,
|
||||
2, /* Elements count */
|
||||
&asn_SPC_NFCResponse_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _NFCResponse_H_
|
||||
#define _NFCResponse_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include "NFCRx.h"
|
||||
#include <NULL.h>
|
||||
#include <constr_CHOICE.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Dependencies */
|
||||
typedef enum NFCResponse_PR {
|
||||
NFCResponse_PR_NOTHING, /* No components present */
|
||||
NFCResponse_PR_nfcRx,
|
||||
NFCResponse_PR_nfcAck
|
||||
} NFCResponse_PR;
|
||||
|
||||
/* NFCResponse */
|
||||
typedef struct NFCResponse {
|
||||
NFCResponse_PR present;
|
||||
union NFCResponse_u {
|
||||
NFCRx_t nfcRx;
|
||||
NULL_t nfcAck;
|
||||
} choice;
|
||||
|
||||
/* Context for parsing across buffer boundaries */
|
||||
asn_struct_ctx_t _asn_ctx;
|
||||
} NFCResponse_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_NFCResponse;
|
||||
extern asn_CHOICE_specifics_t asn_SPC_NFCResponse_specs_1;
|
||||
extern asn_TYPE_member_t asn_MBR_NFCResponse_1[2];
|
||||
extern asn_per_constraints_t asn_PER_type_NFCResponse_constr_1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NFCResponse_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "NFCRx.h"
|
||||
|
||||
asn_TYPE_member_t asn_MBR_NFCRx_1[] = {
|
||||
{ ATF_POINTER, 1, offsetof(struct NFCRx, data),
|
||||
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_OCTET_STRING,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"data"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct NFCRx, rfStatus),
|
||||
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_RfStatus,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"rfStatus"
|
||||
},
|
||||
};
|
||||
static const int asn_MAP_NFCRx_oms_1[] = { 0 };
|
||||
static const ber_tlv_tag_t asn_DEF_NFCRx_tags_1[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
|
||||
};
|
||||
static const asn_TYPE_tag2member_t asn_MAP_NFCRx_tag2el_1[] = {
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* data */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 } /* rfStatus */
|
||||
};
|
||||
asn_SEQUENCE_specifics_t asn_SPC_NFCRx_specs_1 = {
|
||||
sizeof(struct NFCRx),
|
||||
offsetof(struct NFCRx, _asn_ctx),
|
||||
asn_MAP_NFCRx_tag2el_1,
|
||||
2, /* Count of tags in the map */
|
||||
asn_MAP_NFCRx_oms_1, /* Optional members */
|
||||
1, 0, /* Root/Additions */
|
||||
-1, /* First extension addition */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_NFCRx = {
|
||||
"NFCRx",
|
||||
"NFCRx",
|
||||
&asn_OP_SEQUENCE,
|
||||
asn_DEF_NFCRx_tags_1,
|
||||
sizeof(asn_DEF_NFCRx_tags_1)
|
||||
/sizeof(asn_DEF_NFCRx_tags_1[0]), /* 1 */
|
||||
asn_DEF_NFCRx_tags_1, /* Same as above */
|
||||
sizeof(asn_DEF_NFCRx_tags_1)
|
||||
/sizeof(asn_DEF_NFCRx_tags_1[0]), /* 1 */
|
||||
{ 0, 0, SEQUENCE_constraint },
|
||||
asn_MBR_NFCRx_1,
|
||||
2, /* Elements count */
|
||||
&asn_SPC_NFCRx_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _NFCRx_H_
|
||||
#define _NFCRx_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include <OCTET_STRING.h>
|
||||
#include "RfStatus.h"
|
||||
#include <constr_SEQUENCE.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* NFCRx */
|
||||
typedef struct NFCRx {
|
||||
OCTET_STRING_t *data /* OPTIONAL */;
|
||||
RfStatus_t rfStatus;
|
||||
|
||||
/* Context for parsing across buffer boundaries */
|
||||
asn_struct_ctx_t _asn_ctx;
|
||||
} NFCRx_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_NFCRx;
|
||||
extern asn_SEQUENCE_specifics_t asn_SPC_NFCRx_specs_1;
|
||||
extern asn_TYPE_member_t asn_MBR_NFCRx_1[2];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NFCRx_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "NFCSend.h"
|
||||
|
||||
asn_TYPE_member_t asn_MBR_NFCSend_1[] = {
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct NFCSend, data),
|
||||
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_OCTET_STRING,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"data"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct NFCSend, protocol),
|
||||
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_Protocol,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"protocol"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct NFCSend, timeOut),
|
||||
(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_NativeInteger,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"timeOut"
|
||||
},
|
||||
};
|
||||
static const ber_tlv_tag_t asn_DEF_NFCSend_tags_1[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
|
||||
};
|
||||
static const asn_TYPE_tag2member_t asn_MAP_NFCSend_tag2el_1[] = {
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* data */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* protocol */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 } /* timeOut */
|
||||
};
|
||||
asn_SEQUENCE_specifics_t asn_SPC_NFCSend_specs_1 = {
|
||||
sizeof(struct NFCSend),
|
||||
offsetof(struct NFCSend, _asn_ctx),
|
||||
asn_MAP_NFCSend_tag2el_1,
|
||||
3, /* Count of tags in the map */
|
||||
0, 0, 0, /* Optional elements (not needed) */
|
||||
-1, /* First extension addition */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_NFCSend = {
|
||||
"NFCSend",
|
||||
"NFCSend",
|
||||
&asn_OP_SEQUENCE,
|
||||
asn_DEF_NFCSend_tags_1,
|
||||
sizeof(asn_DEF_NFCSend_tags_1)
|
||||
/sizeof(asn_DEF_NFCSend_tags_1[0]), /* 1 */
|
||||
asn_DEF_NFCSend_tags_1, /* Same as above */
|
||||
sizeof(asn_DEF_NFCSend_tags_1)
|
||||
/sizeof(asn_DEF_NFCSend_tags_1[0]), /* 1 */
|
||||
{ 0, 0, SEQUENCE_constraint },
|
||||
asn_MBR_NFCSend_1,
|
||||
3, /* Elements count */
|
||||
&asn_SPC_NFCSend_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _NFCSend_H_
|
||||
#define _NFCSend_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include <OCTET_STRING.h>
|
||||
#include "Protocol.h"
|
||||
#include <NativeInteger.h>
|
||||
#include <constr_SEQUENCE.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* NFCSend */
|
||||
typedef struct NFCSend {
|
||||
OCTET_STRING_t data;
|
||||
Protocol_t protocol;
|
||||
long timeOut;
|
||||
|
||||
/* Context for parsing across buffer boundaries */
|
||||
asn_struct_ctx_t _asn_ctx;
|
||||
} NFCSend_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_NFCSend;
|
||||
extern asn_SEQUENCE_specifics_t asn_SPC_NFCSend_specs_1;
|
||||
extern asn_TYPE_member_t asn_MBR_NFCSend_1[3];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NFCSend_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,308 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <asn_codecs_prim.h>
|
||||
#include <NULL.h>
|
||||
|
||||
/*
|
||||
* NULL basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_NULL_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (5 << 2))
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_NULL = {
|
||||
NULL_free,
|
||||
NULL_print,
|
||||
NULL_compare,
|
||||
NULL_decode_ber,
|
||||
NULL_encode_der, /* Special handling of DER encoding */
|
||||
NULL_decode_xer,
|
||||
NULL_encode_xer,
|
||||
#ifdef ASN_DISABLE_OER_SUPPORT
|
||||
0,
|
||||
0,
|
||||
#else
|
||||
NULL_decode_oer,
|
||||
NULL_encode_oer,
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
||||
#ifdef ASN_DISABLE_PER_SUPPORT
|
||||
0,
|
||||
0,
|
||||
#else
|
||||
NULL_decode_uper, /* Unaligned PER decoder */
|
||||
NULL_encode_uper, /* Unaligned PER encoder */
|
||||
#endif /* ASN_DISABLE_PER_SUPPORT */
|
||||
NULL_random_fill,
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_NULL = {
|
||||
"NULL",
|
||||
"NULL",
|
||||
&asn_OP_NULL,
|
||||
asn_DEF_NULL_tags,
|
||||
sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]),
|
||||
asn_DEF_NULL_tags, /* Same as above */
|
||||
sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]),
|
||||
{ 0, 0, asn_generic_no_constraint },
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
void
|
||||
NULL_free(const asn_TYPE_descriptor_t *td, void *ptr,
|
||||
enum asn_struct_free_method method) {
|
||||
if(td && ptr) {
|
||||
switch(method) {
|
||||
case ASFM_FREE_EVERYTHING:
|
||||
FREEMEM(ptr);
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING:
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING_AND_RESET:
|
||||
memset(ptr, 0, sizeof(NULL_t));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode NULL type.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NULL_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **bool_value,
|
||||
const void *buf_ptr, size_t size, int tag_mode) {
|
||||
NULL_t *st = (NULL_t *)*bool_value;
|
||||
asn_dec_rval_t rval;
|
||||
ber_tlv_len_t length;
|
||||
|
||||
if(st == NULL) {
|
||||
st = (NULL_t *)(*bool_value = CALLOC(1, sizeof(*st)));
|
||||
if(st == NULL) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
ASN_DEBUG("Decoding %s as NULL (tm=%d)", td->name, tag_mode);
|
||||
|
||||
/*
|
||||
* Check tags.
|
||||
*/
|
||||
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, tag_mode, 0,
|
||||
&length, 0);
|
||||
if(rval.code != RC_OK) {
|
||||
return rval;
|
||||
}
|
||||
|
||||
// X.690-201508, #8.8.2, length shall be zero.
|
||||
if(length != 0) {
|
||||
ASN_DEBUG("Decoding %s as NULL failed: too much data", td->name);
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NULL_encode_der(const asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode,
|
||||
ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
asn_enc_rval_t erval;
|
||||
|
||||
erval.encoded = der_write_tags(td, 0, tag_mode, 0, tag, cb, app_key);
|
||||
if(erval.encoded == -1) {
|
||||
erval.failed_type = td;
|
||||
erval.structure_ptr = ptr;
|
||||
}
|
||||
|
||||
ASN__ENCODED_OK(erval);
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NULL_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
asn_enc_rval_t er;
|
||||
|
||||
(void)td;
|
||||
(void)sptr;
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
(void)cb;
|
||||
(void)app_key;
|
||||
|
||||
/* XMLNullValue is empty */
|
||||
er.encoded = 0;
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
|
||||
static enum xer_pbd_rval
|
||||
NULL__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
|
||||
const void *chunk_buf, size_t chunk_size) {
|
||||
(void)td;
|
||||
(void)sptr;
|
||||
(void)chunk_buf; /* Going to be empty according to the rules below. */
|
||||
|
||||
/*
|
||||
* There must be no content in self-terminating <NULL/> tag.
|
||||
*/
|
||||
if(chunk_size)
|
||||
return XPBD_BROKEN_ENCODING;
|
||||
else
|
||||
return XPBD_BODY_CONSUMED;
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
NULL_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const char *opt_mname, const void *buf_ptr, size_t size) {
|
||||
return xer_decode_primitive(opt_codec_ctx, td,
|
||||
sptr, sizeof(NULL_t), opt_mname, buf_ptr, size,
|
||||
NULL__xer_body_decode);
|
||||
}
|
||||
|
||||
int
|
||||
NULL_compare(const asn_TYPE_descriptor_t *td, const void *a, const void *b) {
|
||||
(void)td;
|
||||
(void)a;
|
||||
(void)b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
NULL_print(const asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
(void)td; /* Unused argument */
|
||||
(void)ilevel; /* Unused argument */
|
||||
|
||||
if(sptr) {
|
||||
return (cb("<present>", 9, app_key) < 0) ? -1 : 0;
|
||||
} else {
|
||||
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ASN_DISABLE_OER_SUPPORT
|
||||
|
||||
asn_dec_rval_t
|
||||
NULL_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, void **sptr,
|
||||
const void *ptr, size_t size) {
|
||||
asn_dec_rval_t rv = {RC_OK, 0};
|
||||
(void)opt_codec_ctx;
|
||||
(void)td;
|
||||
(void)constraints;
|
||||
(void)ptr;
|
||||
(void)size;
|
||||
|
||||
if(!*sptr) {
|
||||
*sptr = MALLOC(sizeof(NULL_t));
|
||||
if(*sptr) {
|
||||
*(NULL_t *)*sptr = 0;
|
||||
} else {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NULL_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, const void *sptr,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
asn_enc_rval_t er;
|
||||
|
||||
(void)td;
|
||||
(void)sptr;
|
||||
(void)constraints;
|
||||
(void)cb;
|
||||
(void)app_key;
|
||||
|
||||
er.encoded = 0; /* Encoding in 0 bytes. */
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
||||
|
||||
#ifndef ASN_DISABLE_PER_SUPPORT
|
||||
|
||||
asn_dec_rval_t
|
||||
NULL_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr,
|
||||
asn_per_data_t *pd) {
|
||||
asn_dec_rval_t rv;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)td;
|
||||
(void)constraints;
|
||||
(void)pd;
|
||||
|
||||
if(!*sptr) {
|
||||
*sptr = MALLOC(sizeof(NULL_t));
|
||||
if(*sptr) {
|
||||
*(NULL_t *)*sptr = 0;
|
||||
} else {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NULL type does not have content octets.
|
||||
*/
|
||||
|
||||
rv.code = RC_OK;
|
||||
rv.consumed = 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NULL_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, const void *sptr,
|
||||
asn_per_outp_t *po) {
|
||||
asn_enc_rval_t er;
|
||||
|
||||
(void)td;
|
||||
(void)constraints;
|
||||
(void)sptr;
|
||||
(void)po;
|
||||
|
||||
er.encoded = 0;
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
#endif /* ASN_DISABLE_PER_SUPPORT */
|
||||
|
||||
asn_random_fill_result_t
|
||||
NULL_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const asn_encoding_constraints_t *constr,
|
||||
size_t max_length) {
|
||||
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
|
||||
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
|
||||
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
|
||||
NULL_t *st = *sptr;
|
||||
|
||||
(void)td;
|
||||
(void)constr;
|
||||
|
||||
if(max_length == 0) return result_skipped;
|
||||
|
||||
if(st == NULL) {
|
||||
st = (NULL_t *)(*sptr = CALLOC(1, sizeof(*st)));
|
||||
if(st == NULL) {
|
||||
return result_failed;
|
||||
}
|
||||
}
|
||||
|
||||
return result_ok;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_TYPE_NULL_H
|
||||
#define ASN_TYPE_NULL_H
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The value of the NULL type is meaningless.
|
||||
* Use the BOOLEAN type if you need to carry true/false semantics.
|
||||
*/
|
||||
typedef int NULL_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_NULL;
|
||||
extern asn_TYPE_operation_t asn_OP_NULL;
|
||||
|
||||
asn_struct_free_f NULL_free;
|
||||
asn_struct_print_f NULL_print;
|
||||
asn_struct_compare_f NULL_compare;
|
||||
ber_type_decoder_f NULL_decode_ber;
|
||||
der_type_encoder_f NULL_encode_der;
|
||||
xer_type_decoder_f NULL_decode_xer;
|
||||
xer_type_encoder_f NULL_encode_xer;
|
||||
oer_type_decoder_f NULL_decode_oer;
|
||||
oer_type_encoder_f NULL_encode_oer;
|
||||
per_type_decoder_f NULL_decode_uper;
|
||||
per_type_encoder_f NULL_encode_uper;
|
||||
asn_random_fill_f NULL_random_fill;
|
||||
|
||||
#define NULL_constraint asn_generic_no_constraint
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NULL_H */
|
||||
@@ -0,0 +1,226 @@
|
||||
/*-
|
||||
* Copyright (c) 2004, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* Read the NativeInteger.h for the explanation wrt. differences between
|
||||
* INTEGER and NativeInteger.
|
||||
* Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
|
||||
* implementation deals with the standard (machine-specific) representation
|
||||
* of them instead of using the platform-independent buffer.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <NativeEnumerated.h>
|
||||
|
||||
/*
|
||||
* NativeEnumerated basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (10 << 2))
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_NativeEnumerated = {
|
||||
NativeInteger_free,
|
||||
NativeInteger_print,
|
||||
NativeInteger_compare,
|
||||
NativeInteger_decode_ber,
|
||||
NativeInteger_encode_der,
|
||||
NativeInteger_decode_xer,
|
||||
NativeEnumerated_encode_xer,
|
||||
#ifdef ASN_DISABLE_OER_SUPPORT
|
||||
0,
|
||||
0,
|
||||
#else
|
||||
NativeEnumerated_decode_oer,
|
||||
NativeEnumerated_encode_oer,
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
||||
#ifdef ASN_DISABLE_PER_SUPPORT
|
||||
0,
|
||||
0,
|
||||
#else
|
||||
NativeEnumerated_decode_uper,
|
||||
NativeEnumerated_encode_uper,
|
||||
#endif /* ASN_DISABLE_PER_SUPPORT */
|
||||
NativeEnumerated_random_fill,
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = {
|
||||
"ENUMERATED", /* The ASN.1 type is still ENUMERATED */
|
||||
"ENUMERATED",
|
||||
&asn_OP_NativeEnumerated,
|
||||
asn_DEF_NativeEnumerated_tags,
|
||||
sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
|
||||
asn_DEF_NativeEnumerated_tags, /* Same as above */
|
||||
sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]),
|
||||
{ 0, 0, asn_generic_no_constraint },
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeEnumerated_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_enc_rval_t er;
|
||||
const long *native = (const long *)sptr;
|
||||
const asn_INTEGER_enum_map_t *el;
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!native) ASN__ENCODE_FAILED;
|
||||
|
||||
el = INTEGER_map_value2enum(specs, *native);
|
||||
if(el) {
|
||||
er.encoded =
|
||||
asn__format_to_callback(cb, app_key, "<%s/>", el->enum_name);
|
||||
if(er.encoded < 0) ASN__ENCODE_FAILED;
|
||||
ASN__ENCODED_OK(er);
|
||||
} else {
|
||||
ASN_DEBUG(
|
||||
"ASN.1 forbids dealing with "
|
||||
"unknown value of ENUMERATED type");
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeEnumerated_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
void **sptr, asn_per_data_t *pd) {
|
||||
const asn_INTEGER_specifics_t *specs = td->specifics;
|
||||
asn_dec_rval_t rval = { RC_OK, 0 };
|
||||
long *native = (long *)*sptr;
|
||||
const asn_per_constraint_t *ct;
|
||||
long value;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
|
||||
if(constraints) ct = &constraints->value;
|
||||
else if(td->encoding_constraints.per_constraints)
|
||||
ct = &td->encoding_constraints.per_constraints->value;
|
||||
else ASN__DECODE_FAILED; /* Mandatory! */
|
||||
if(!specs) ASN__DECODE_FAILED;
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
ASN_DEBUG("Decoding %s as NativeEnumerated", td->name);
|
||||
|
||||
if(ct->flags & APC_EXTENSIBLE) {
|
||||
int inext = per_get_few_bits(pd, 1);
|
||||
if(inext < 0) ASN__DECODE_STARVED;
|
||||
if(inext) ct = 0;
|
||||
}
|
||||
|
||||
if(ct && ct->range_bits >= 0) {
|
||||
value = per_get_few_bits(pd, ct->range_bits);
|
||||
if(value < 0) ASN__DECODE_STARVED;
|
||||
if(value >= (specs->extension
|
||||
? specs->extension - 1 : specs->map_count))
|
||||
ASN__DECODE_FAILED;
|
||||
} else {
|
||||
if(!specs->extension)
|
||||
ASN__DECODE_FAILED;
|
||||
/*
|
||||
* X.691, #10.6: normally small non-negative whole number;
|
||||
*/
|
||||
value = uper_get_nsnnwn(pd);
|
||||
if(value < 0) ASN__DECODE_STARVED;
|
||||
value += specs->extension - 1;
|
||||
if(value >= specs->map_count)
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
*native = specs->value2enum[value].nat_value;
|
||||
ASN_DEBUG("Decoded %s = %ld", td->name, *native);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int
|
||||
NativeEnumerated__compar_value2enum(const void *ap, const void *bp) {
|
||||
const asn_INTEGER_enum_map_t *a = ap;
|
||||
const asn_INTEGER_enum_map_t *b = bp;
|
||||
if(a->nat_value == b->nat_value)
|
||||
return 0;
|
||||
if(a->nat_value < b->nat_value)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeEnumerated_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_enc_rval_t er;
|
||||
long native, value;
|
||||
const asn_per_constraint_t *ct;
|
||||
int inext = 0;
|
||||
asn_INTEGER_enum_map_t key;
|
||||
const asn_INTEGER_enum_map_t *kf;
|
||||
|
||||
if(!sptr) ASN__ENCODE_FAILED;
|
||||
if(!specs) ASN__ENCODE_FAILED;
|
||||
|
||||
if(constraints) ct = &constraints->value;
|
||||
else if(td->encoding_constraints.per_constraints)
|
||||
ct = &td->encoding_constraints.per_constraints->value;
|
||||
else ASN__ENCODE_FAILED; /* Mandatory! */
|
||||
|
||||
ASN_DEBUG("Encoding %s as NativeEnumerated", td->name);
|
||||
|
||||
er.encoded = 0;
|
||||
|
||||
native = *(const long *)sptr;
|
||||
|
||||
key.nat_value = native;
|
||||
kf = bsearch(&key, specs->value2enum, specs->map_count,
|
||||
sizeof(key), NativeEnumerated__compar_value2enum);
|
||||
if(!kf) {
|
||||
ASN_DEBUG("No element corresponds to %ld", native);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
value = kf - specs->value2enum;
|
||||
|
||||
if(ct->range_bits >= 0) {
|
||||
int cmpWith = specs->extension
|
||||
? specs->extension - 1 : specs->map_count;
|
||||
if(value >= cmpWith)
|
||||
inext = 1;
|
||||
}
|
||||
if(ct->flags & APC_EXTENSIBLE) {
|
||||
if(per_put_few_bits(po, inext, 1))
|
||||
ASN__ENCODE_FAILED;
|
||||
if(inext) ct = 0;
|
||||
} else if(inext) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
if(ct && ct->range_bits >= 0) {
|
||||
if(per_put_few_bits(po, value, ct->range_bits))
|
||||
ASN__ENCODE_FAILED;
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
if(!specs->extension)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
/*
|
||||
* X.691, #10.6: normally small non-negative whole number;
|
||||
*/
|
||||
ASN_DEBUG("value = %ld, ext = %d, inext = %d, res = %ld",
|
||||
value, specs->extension, inext,
|
||||
value - (inext ? (specs->extension - 1) : 0));
|
||||
if(uper_put_nsnnwn(po, value - (inext ? (specs->extension - 1) : 0)))
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* This type differs from the standard ENUMERATED in that it is modelled using
|
||||
* the fixed machine type (long, int, short), so it can hold only values of
|
||||
* limited length. There is no type (i.e., NativeEnumerated_t, any integer type
|
||||
* will do).
|
||||
* This type may be used when integer range is limited by subtype constraints.
|
||||
*/
|
||||
#ifndef _NativeEnumerated_H_
|
||||
#define _NativeEnumerated_H_
|
||||
|
||||
#include <NativeInteger.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated;
|
||||
extern asn_TYPE_operation_t asn_OP_NativeEnumerated;
|
||||
|
||||
xer_type_encoder_f NativeEnumerated_encode_xer;
|
||||
oer_type_decoder_f NativeEnumerated_decode_oer;
|
||||
oer_type_encoder_f NativeEnumerated_encode_oer;
|
||||
per_type_decoder_f NativeEnumerated_decode_uper;
|
||||
per_type_encoder_f NativeEnumerated_encode_uper;
|
||||
|
||||
#define NativeEnumerated_free NativeInteger_free
|
||||
#define NativeEnumerated_print NativeInteger_print
|
||||
#define NativeEnumerated_compare NativeInteger_compare
|
||||
#define NativeEnumerated_random_fill NativeInteger_random_fill
|
||||
#define NativeEnumerated_constraint asn_generic_no_constraint
|
||||
#define NativeEnumerated_decode_ber NativeInteger_decode_ber
|
||||
#define NativeEnumerated_encode_der NativeInteger_encode_der
|
||||
#define NativeEnumerated_decode_xer NativeInteger_decode_xer
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NativeEnumerated_H_ */
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_DISABLE_OER_SUPPORT
|
||||
|
||||
#include <asn_internal.h>
|
||||
#include <NativeEnumerated.h>
|
||||
#include <errno.h>
|
||||
|
||||
static long
|
||||
asn__nativeenumerated_convert(const uint8_t *b, const uint8_t *end) {
|
||||
unsigned long value;
|
||||
|
||||
/* Perform the sign initialization */
|
||||
/* Actually value = -(*b >> 7); gains nothing, yet unreadable! */
|
||||
if((*b >> 7)) {
|
||||
value = (unsigned long)(-1);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
/* Conversion engine */
|
||||
for(; b < end; b++) {
|
||||
value = (value << 8) | *b;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeEnumerated_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
void **nint_ptr, const void *ptr, size_t size) {
|
||||
asn_dec_rval_t rval = {RC_OK, 0};
|
||||
long *native = (long *)*nint_ptr;
|
||||
const uint8_t *b = ptr;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
(void)constraints;
|
||||
|
||||
if(size < 1) {
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
|
||||
if((*b & 0x80) == 0) {
|
||||
/*
|
||||
* X.696 (08/2015) #11.2 Short form for Enumerated.
|
||||
*/
|
||||
if(!native) {
|
||||
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
*native = *b;
|
||||
rval.consumed = 1;
|
||||
} else {
|
||||
/*
|
||||
* X.696 (08/2015) #11.4 Long form for Enumerated.
|
||||
*/
|
||||
size_t length = *b & 0x7f;
|
||||
const uint8_t *bend;
|
||||
long value;
|
||||
|
||||
if(length < 1 || length > sizeof(*native)) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
if((1 + length) > size) {
|
||||
ASN__DECODE_STARVED;
|
||||
}
|
||||
b++;
|
||||
bend = b + length;
|
||||
|
||||
value = asn__nativeenumerated_convert(b, bend);
|
||||
if(value < 0) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
if(specs && specs->field_unsigned) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
*native = value;
|
||||
|
||||
rval.consumed = (1 + length);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode as Canonical OER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
NativeEnumerated_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
const void *sptr, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
asn_enc_rval_t er;
|
||||
long native;
|
||||
|
||||
(void)constraints;
|
||||
|
||||
if(!sptr) ASN__ENCODE_FAILED;
|
||||
|
||||
native = *(const long *)sptr;
|
||||
|
||||
if(native >= 0 && native <= 127) {
|
||||
/* #11.2 Short form */
|
||||
uint8_t b = native;
|
||||
er.encoded = 1;
|
||||
if(cb(&b, er.encoded, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
ASN__ENCODED_OK(er);
|
||||
} else {
|
||||
/* #11.2 Long form */
|
||||
uint8_t buf[1 + sizeof(native)];
|
||||
uint8_t *b = &buf[sizeof(native)]; /* Last addressable */
|
||||
long final_pattern = -1 * (native < 0);
|
||||
|
||||
for(;;) {
|
||||
*b-- = native;
|
||||
native >>= 8;
|
||||
if(native == final_pattern) {
|
||||
if(final_pattern) {
|
||||
if((b[1] & 0x80)) break;
|
||||
} else {
|
||||
if(!(b[1] & 0x80)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*b = 0x80 | (&buf[sizeof(native)] - b);
|
||||
er.encoded = 1 + (&buf[sizeof(native)] - b);
|
||||
if(cb(b, er.encoded, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
||||
@@ -0,0 +1,484 @@
|
||||
/*-
|
||||
* Copyright (c) 2004, 2005, 2006 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* Read the NativeInteger.h for the explanation wrt. differences between
|
||||
* INTEGER and NativeInteger.
|
||||
* Basically, both are decoders and encoders of ASN.1 INTEGER type, but this
|
||||
* implementation deals with the standard (machine-specific) representation
|
||||
* of them instead of using the platform-independent buffer.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <NativeInteger.h>
|
||||
|
||||
/*
|
||||
* NativeInteger basic type description.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
|
||||
};
|
||||
asn_TYPE_operation_t asn_OP_NativeInteger = {
|
||||
NativeInteger_free,
|
||||
NativeInteger_print,
|
||||
NativeInteger_compare,
|
||||
NativeInteger_decode_ber,
|
||||
NativeInteger_encode_der,
|
||||
NativeInteger_decode_xer,
|
||||
NativeInteger_encode_xer,
|
||||
#ifdef ASN_DISABLE_OER_SUPPORT
|
||||
0,
|
||||
0,
|
||||
#else
|
||||
NativeInteger_decode_oer, /* OER decoder */
|
||||
NativeInteger_encode_oer, /* Canonical OER encoder */
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
||||
#ifdef ASN_DISABLE_PER_SUPPORT
|
||||
0,
|
||||
0,
|
||||
#else
|
||||
NativeInteger_decode_uper, /* Unaligned PER decoder */
|
||||
NativeInteger_encode_uper, /* Unaligned PER encoder */
|
||||
#endif /* ASN_DISABLE_PER_SUPPORT */
|
||||
NativeInteger_random_fill,
|
||||
0 /* Use generic outmost tag fetcher */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_NativeInteger = {
|
||||
"INTEGER", /* The ASN.1 type is still INTEGER */
|
||||
"INTEGER",
|
||||
&asn_OP_NativeInteger,
|
||||
asn_DEF_NativeInteger_tags,
|
||||
sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
|
||||
asn_DEF_NativeInteger_tags, /* Same as above */
|
||||
sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]),
|
||||
{ 0, 0, asn_generic_no_constraint },
|
||||
0, 0, /* No members */
|
||||
0 /* No specifics */
|
||||
};
|
||||
|
||||
/*
|
||||
* Decode INTEGER type.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NativeInteger_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **nint_ptr,
|
||||
const void *buf_ptr, size_t size, int tag_mode) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
long *native = (long *)*nint_ptr;
|
||||
asn_dec_rval_t rval;
|
||||
ber_tlv_len_t length;
|
||||
|
||||
/*
|
||||
* If the structure is not there, allocate it.
|
||||
*/
|
||||
if(native == NULL) {
|
||||
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
|
||||
if(native == NULL) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
ASN_DEBUG("Decoding %s as INTEGER (tm=%d)",
|
||||
td->name, tag_mode);
|
||||
|
||||
/*
|
||||
* Check tags.
|
||||
*/
|
||||
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
|
||||
tag_mode, 0, &length, 0);
|
||||
if(rval.code != RC_OK)
|
||||
return rval;
|
||||
|
||||
ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
|
||||
|
||||
/*
|
||||
* Make sure we have this length.
|
||||
*/
|
||||
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
|
||||
size -= rval.consumed;
|
||||
if(length > (ber_tlv_len_t)size) {
|
||||
rval.code = RC_WMORE;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* ASN.1 encoded INTEGER: buf_ptr, length
|
||||
* Fill the native, at the same time checking for overflow.
|
||||
* If overflow occurred, return with RC_FAIL.
|
||||
*/
|
||||
{
|
||||
INTEGER_t tmp;
|
||||
union {
|
||||
const void *constbuf;
|
||||
void *nonconstbuf;
|
||||
} unconst_buf;
|
||||
long l;
|
||||
|
||||
unconst_buf.constbuf = buf_ptr;
|
||||
tmp.buf = (uint8_t *)unconst_buf.nonconstbuf;
|
||||
tmp.size = length;
|
||||
|
||||
if((specs&&specs->field_unsigned)
|
||||
? asn_INTEGER2ulong(&tmp, (unsigned long *)&l) /* sic */
|
||||
: asn_INTEGER2long(&tmp, &l)) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
*native = l;
|
||||
}
|
||||
|
||||
rval.code = RC_OK;
|
||||
rval.consumed += length;
|
||||
|
||||
ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)",
|
||||
(long)rval.consumed, (long)length, td->name, (long)*native);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode the NativeInteger using the standard INTEGER type DER encoder.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
NativeInteger_encode_der(const asn_TYPE_descriptor_t *sd, const void *ptr,
|
||||
int tag_mode, ber_tlv_tag_t tag,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
unsigned long native = *(const unsigned long *)ptr; /* Disable sign ext. */
|
||||
asn_enc_rval_t erval;
|
||||
INTEGER_t tmp;
|
||||
|
||||
#ifdef WORDS_BIGENDIAN /* Opportunistic optimization */
|
||||
|
||||
tmp.buf = (uint8_t *)&native;
|
||||
tmp.size = sizeof(native);
|
||||
|
||||
#else /* Works even if WORDS_BIGENDIAN is not set where should've been */
|
||||
uint8_t buf[sizeof(native)];
|
||||
uint8_t *p;
|
||||
|
||||
/* Prepare a fake INTEGER */
|
||||
for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8)
|
||||
*p = (uint8_t)native;
|
||||
|
||||
tmp.buf = buf;
|
||||
tmp.size = sizeof(buf);
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
|
||||
/* Encode fake INTEGER */
|
||||
erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key);
|
||||
if(erval.structure_ptr == &tmp) {
|
||||
erval.structure_ptr = ptr;
|
||||
}
|
||||
return erval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode the chunk of XML text encoding INTEGER.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
NativeInteger_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const char *opt_mname, const void *buf_ptr,
|
||||
size_t size) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval;
|
||||
INTEGER_t st;
|
||||
void *st_ptr = (void *)&st;
|
||||
long *native = (long *)*sptr;
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memset(&st, 0, sizeof(st));
|
||||
rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr,
|
||||
opt_mname, buf_ptr, size);
|
||||
if(rval.code == RC_OK) {
|
||||
long l;
|
||||
if((specs&&specs->field_unsigned)
|
||||
? asn_INTEGER2ulong(&st, (unsigned long *)&l) /* sic */
|
||||
: asn_INTEGER2long(&st, &l)) {
|
||||
rval.code = RC_FAIL;
|
||||
rval.consumed = 0;
|
||||
} else {
|
||||
*native = l;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Cannot restart from the middle;
|
||||
* there is no place to save state in the native type.
|
||||
* Request a continuation from the very beginning.
|
||||
*/
|
||||
rval.consumed = 0;
|
||||
}
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st);
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeInteger_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, enum xer_encoder_flags_e flags,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
char scratch[32]; /* Enough for 64-bit int */
|
||||
asn_enc_rval_t er;
|
||||
const long *native = (const long *)sptr;
|
||||
|
||||
(void)ilevel;
|
||||
(void)flags;
|
||||
|
||||
if(!native) ASN__ENCODE_FAILED;
|
||||
|
||||
er.encoded = snprintf(scratch, sizeof(scratch),
|
||||
(specs && specs->field_unsigned)
|
||||
? "%lu" : "%ld", *native);
|
||||
if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch)
|
||||
|| cb(scratch, er.encoded, app_key) < 0)
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
#ifndef ASN_DISABLE_PER_SUPPORT
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeInteger_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints, void **sptr,
|
||||
asn_per_data_t *pd) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval;
|
||||
long *native = (long *)*sptr;
|
||||
INTEGER_t tmpint;
|
||||
void *tmpintptr = &tmpint;
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name);
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*sptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memset(&tmpint, 0, sizeof tmpint);
|
||||
rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints,
|
||||
&tmpintptr, pd);
|
||||
if(rval.code == RC_OK) {
|
||||
if((specs&&specs->field_unsigned)
|
||||
? asn_INTEGER2ulong(&tmpint, (unsigned long *)native)
|
||||
: asn_INTEGER2long(&tmpint, native))
|
||||
rval.code = RC_FAIL;
|
||||
else
|
||||
ASN_DEBUG("NativeInteger %s got value %ld",
|
||||
td->name, *native);
|
||||
}
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
NativeInteger_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_enc_rval_t er;
|
||||
long native;
|
||||
INTEGER_t tmpint;
|
||||
|
||||
if(!sptr) ASN__ENCODE_FAILED;
|
||||
|
||||
native = *(const long *)sptr;
|
||||
|
||||
ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native);
|
||||
|
||||
memset(&tmpint, 0, sizeof(tmpint));
|
||||
if((specs&&specs->field_unsigned)
|
||||
? asn_ulong2INTEGER(&tmpint, native)
|
||||
: asn_long2INTEGER(&tmpint, native))
|
||||
ASN__ENCODE_FAILED;
|
||||
er = INTEGER_encode_uper(td, constraints, &tmpint, po);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
return er;
|
||||
}
|
||||
|
||||
#endif /* ASN_DISABLE_PER_SUPPORT */
|
||||
|
||||
/*
|
||||
* INTEGER specific human-readable output.
|
||||
*/
|
||||
int
|
||||
NativeInteger_print(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
const long *native = (const long *)sptr;
|
||||
char scratch[32]; /* Enough for 64-bit int */
|
||||
int ret;
|
||||
|
||||
(void)td; /* Unused argument */
|
||||
(void)ilevel; /* Unused argument */
|
||||
|
||||
if(native) {
|
||||
long value = *native;
|
||||
ret = snprintf(scratch, sizeof(scratch),
|
||||
(specs && specs->field_unsigned) ? "%lu" : "%ld", value);
|
||||
assert(ret > 0 && (size_t)ret < sizeof(scratch));
|
||||
if(cb(scratch, ret, app_key) < 0) return -1;
|
||||
if(specs && (value >= 0 || !specs->field_unsigned)) {
|
||||
const asn_INTEGER_enum_map_t *el =
|
||||
INTEGER_map_value2enum(specs, value);
|
||||
if(el) {
|
||||
if(cb(" (", 2, app_key) < 0) return -1;
|
||||
if(cb(el->enum_name, el->enum_len, app_key) < 0) return -1;
|
||||
if(cb(")", 1, app_key) < 0) return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NativeInteger_free(const asn_TYPE_descriptor_t *td, void *ptr,
|
||||
enum asn_struct_free_method method) {
|
||||
if(!td || !ptr)
|
||||
return;
|
||||
|
||||
ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)",
|
||||
td->name, method, ptr);
|
||||
|
||||
switch(method) {
|
||||
case ASFM_FREE_EVERYTHING:
|
||||
FREEMEM(ptr);
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING:
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING_AND_RESET:
|
||||
memset(ptr, 0, sizeof(long));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
NativeInteger_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const void *bptr) {
|
||||
(void)td;
|
||||
|
||||
if(aptr && bptr) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
if(specs && specs->field_unsigned) {
|
||||
const unsigned long *a = aptr;
|
||||
const unsigned long *b = bptr;
|
||||
if(*a < *b) {
|
||||
return -1;
|
||||
} else if(*a > *b) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
const long *a = aptr;
|
||||
const long *b = bptr;
|
||||
if(*a < *b) {
|
||||
return -1;
|
||||
} else if(*a > *b) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if(!aptr) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
asn_random_fill_result_t
|
||||
NativeInteger_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const asn_encoding_constraints_t *constraints,
|
||||
size_t max_length) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
|
||||
asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
|
||||
asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
|
||||
long *st = *sptr;
|
||||
const asn_INTEGER_enum_map_t *emap;
|
||||
size_t emap_len;
|
||||
intmax_t value;
|
||||
int find_inside_map;
|
||||
|
||||
if(max_length == 0) return result_skipped;
|
||||
|
||||
if(st == NULL) {
|
||||
st = (long *)CALLOC(1, sizeof(*st));
|
||||
if(st == NULL) {
|
||||
return result_failed;
|
||||
}
|
||||
}
|
||||
|
||||
if(specs) {
|
||||
emap = specs->value2enum;
|
||||
emap_len = specs->map_count;
|
||||
if(specs->strict_enumeration) {
|
||||
find_inside_map = emap_len > 0;
|
||||
} else {
|
||||
find_inside_map = emap_len ? asn_random_between(0, 1) : 0;
|
||||
}
|
||||
} else {
|
||||
emap = 0;
|
||||
emap_len = 0;
|
||||
find_inside_map = 0;
|
||||
}
|
||||
|
||||
if(find_inside_map) {
|
||||
assert(emap_len > 0);
|
||||
value = emap[asn_random_between(0, emap_len - 1)].nat_value;
|
||||
} else {
|
||||
const asn_per_constraints_t *ct;
|
||||
|
||||
static const long variants[] = {
|
||||
-65536, -65535, -65534, -32769, -32768, -32767, -16385, -16384,
|
||||
-16383, -257, -256, -255, -254, -129, -128, -127,
|
||||
-126, -1, 0, 1, 126, 127, 128, 129,
|
||||
254, 255, 256, 257, 16383, 16384, 16385, 32767,
|
||||
32768, 32769, 65534, 65535, 65536, 65537};
|
||||
if(specs && specs->field_unsigned) {
|
||||
assert(variants[18] == 0);
|
||||
value = variants[asn_random_between(
|
||||
18, sizeof(variants) / sizeof(variants[0]) - 1)];
|
||||
} else {
|
||||
value = variants[asn_random_between(
|
||||
0, sizeof(variants) / sizeof(variants[0]) - 1)];
|
||||
}
|
||||
|
||||
if(!constraints) constraints = &td->encoding_constraints;
|
||||
ct = constraints ? constraints->per_constraints : 0;
|
||||
if(ct && (ct->value.flags & APC_CONSTRAINED)) {
|
||||
if(value < ct->value.lower_bound || value > ct->value.upper_bound) {
|
||||
value = asn_random_between(ct->value.lower_bound,
|
||||
ct->value.upper_bound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*sptr = st;
|
||||
*st = value;
|
||||
return result_ok;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*-
|
||||
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* This type differs from the standard INTEGER in that it is modelled using
|
||||
* the fixed machine type (long, int, short), so it can hold only values of
|
||||
* limited length. There is no type (i.e., NativeInteger_t, any integer type
|
||||
* will do).
|
||||
* This type may be used when integer range is limited by subtype constraints.
|
||||
*/
|
||||
#ifndef _NativeInteger_H_
|
||||
#define _NativeInteger_H_
|
||||
|
||||
#include <asn_application.h>
|
||||
#include <INTEGER.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_NativeInteger;
|
||||
extern asn_TYPE_operation_t asn_OP_NativeInteger;
|
||||
|
||||
asn_struct_free_f NativeInteger_free;
|
||||
asn_struct_print_f NativeInteger_print;
|
||||
asn_struct_compare_f NativeInteger_compare;
|
||||
ber_type_decoder_f NativeInteger_decode_ber;
|
||||
der_type_encoder_f NativeInteger_encode_der;
|
||||
xer_type_decoder_f NativeInteger_decode_xer;
|
||||
xer_type_encoder_f NativeInteger_encode_xer;
|
||||
oer_type_decoder_f NativeInteger_decode_oer;
|
||||
oer_type_encoder_f NativeInteger_encode_oer;
|
||||
per_type_decoder_f NativeInteger_decode_uper;
|
||||
per_type_encoder_f NativeInteger_encode_uper;
|
||||
asn_random_fill_f NativeInteger_random_fill;
|
||||
|
||||
#define NativeInteger_constraint asn_generic_no_constraint
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NativeInteger_H_ */
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_DISABLE_OER_SUPPORT
|
||||
|
||||
#include <asn_internal.h>
|
||||
#include <NativeInteger.h>
|
||||
#include <errno.h>
|
||||
|
||||
asn_dec_rval_t
|
||||
NativeInteger_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
void **nint_ptr, const void *ptr, size_t size) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
asn_dec_rval_t rval = {RC_OK, 0};
|
||||
long *native = (long *)*nint_ptr;
|
||||
INTEGER_t tmpint;
|
||||
INTEGER_t *tmpintptr = &tmpint;
|
||||
|
||||
memset(&tmpint, 0, sizeof(tmpint));
|
||||
|
||||
if(!native) {
|
||||
native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native)));
|
||||
if(!native) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* OPTIMIZATION: Encode directly rather than passing through INTEGER.
|
||||
* Saves a memory allocation.
|
||||
*/
|
||||
rval = INTEGER_decode_oer(opt_codec_ctx, td, constraints,
|
||||
(void **)&tmpintptr, ptr, size);
|
||||
if(rval.code != RC_OK) {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
return rval;
|
||||
}
|
||||
|
||||
if(specs && specs->field_unsigned) {
|
||||
unsigned long ul;
|
||||
int ok = asn_INTEGER2ulong(&tmpint, &ul) == 0;
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
if(ok) {
|
||||
*native = ul;
|
||||
} else {
|
||||
rval.code = RC_FAIL;
|
||||
return rval;
|
||||
}
|
||||
} else {
|
||||
long l;
|
||||
int ok = asn_INTEGER2long(&tmpint, &l) == 0;
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
if(ok) {
|
||||
*native = l;
|
||||
} else {
|
||||
rval.code = RC_FAIL;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode as Canonical OER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
NativeInteger_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
const void *sptr, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
const asn_INTEGER_specifics_t *specs =
|
||||
(const asn_INTEGER_specifics_t *)td->specifics;
|
||||
INTEGER_t tmpint;
|
||||
long native;
|
||||
|
||||
if(!sptr) ASN__ENCODE_FAILED;
|
||||
|
||||
native = *(const long *)sptr;
|
||||
memset(&tmpint, 0, sizeof(tmpint));
|
||||
|
||||
ASN_DEBUG("Encoding %s %ld as NativeInteger", td ? td->name : "", native);
|
||||
|
||||
if((specs && specs->field_unsigned) ? asn_ulong2INTEGER(&tmpint, native)
|
||||
: asn_long2INTEGER(&tmpint, native)) {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
asn_enc_rval_t er =
|
||||
INTEGER_encode_oer(td, constraints, &tmpint, cb, app_key);
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint);
|
||||
return er;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
||||
@@ -0,0 +1,100 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef _OCTET_STRING_H_
|
||||
#define _OCTET_STRING_H_
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct OCTET_STRING {
|
||||
uint8_t *buf; /* Buffer with consecutive OCTET_STRING bits */
|
||||
size_t size; /* Size of the buffer */
|
||||
|
||||
asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */
|
||||
} OCTET_STRING_t;
|
||||
|
||||
extern asn_TYPE_descriptor_t asn_DEF_OCTET_STRING;
|
||||
extern asn_TYPE_operation_t asn_OP_OCTET_STRING;
|
||||
|
||||
asn_struct_free_f OCTET_STRING_free;
|
||||
asn_struct_print_f OCTET_STRING_print;
|
||||
asn_struct_print_f OCTET_STRING_print_utf8;
|
||||
asn_struct_compare_f OCTET_STRING_compare;
|
||||
ber_type_decoder_f OCTET_STRING_decode_ber;
|
||||
der_type_encoder_f OCTET_STRING_encode_der;
|
||||
xer_type_decoder_f OCTET_STRING_decode_xer_hex; /* Hexadecimal */
|
||||
xer_type_decoder_f OCTET_STRING_decode_xer_binary; /* 01010111010 */
|
||||
xer_type_decoder_f OCTET_STRING_decode_xer_utf8; /* ASCII/UTF-8 */
|
||||
xer_type_encoder_f OCTET_STRING_encode_xer;
|
||||
xer_type_encoder_f OCTET_STRING_encode_xer_utf8;
|
||||
oer_type_decoder_f OCTET_STRING_decode_oer;
|
||||
oer_type_encoder_f OCTET_STRING_encode_oer;
|
||||
per_type_decoder_f OCTET_STRING_decode_uper;
|
||||
per_type_encoder_f OCTET_STRING_encode_uper;
|
||||
asn_random_fill_f OCTET_STRING_random_fill;
|
||||
|
||||
#define OCTET_STRING_constraint asn_generic_no_constraint
|
||||
#define OCTET_STRING_decode_xer OCTET_STRING_decode_xer_hex
|
||||
|
||||
/******************************
|
||||
* Handy conversion routines. *
|
||||
******************************/
|
||||
|
||||
/*
|
||||
* This function clears the previous value of the OCTET STRING (if any)
|
||||
* and then allocates a new memory with the specified content (str/size).
|
||||
* If size = -1, the size of the original string will be determined
|
||||
* using strlen(str).
|
||||
* If str equals to NULL, the function will silently clear the
|
||||
* current contents of the OCTET STRING.
|
||||
* Returns 0 if it was possible to perform operation, -1 otherwise.
|
||||
*/
|
||||
int OCTET_STRING_fromBuf(OCTET_STRING_t *s, const char *str, int size);
|
||||
|
||||
/* Handy conversion from the C string into the OCTET STRING. */
|
||||
#define OCTET_STRING_fromString(s, str) OCTET_STRING_fromBuf(s, str, -1)
|
||||
|
||||
/*
|
||||
* Allocate and fill the new OCTET STRING and return a pointer to the newly
|
||||
* allocated object. NULL is permitted in str: the function will just allocate
|
||||
* empty OCTET STRING.
|
||||
*/
|
||||
OCTET_STRING_t *OCTET_STRING_new_fromBuf(const asn_TYPE_descriptor_t *td,
|
||||
const char *str, int size);
|
||||
|
||||
/****************************
|
||||
* Internally useful stuff. *
|
||||
****************************/
|
||||
|
||||
typedef struct asn_OCTET_STRING_specifics_s {
|
||||
/*
|
||||
* Target structure description.
|
||||
*/
|
||||
unsigned struct_size; /* Size of the structure */
|
||||
unsigned ctx_offset; /* Offset of the asn_struct_ctx_t member */
|
||||
|
||||
enum asn_OS_Subvariant {
|
||||
ASN_OSUBV_ANY, /* The open type (ANY) */
|
||||
ASN_OSUBV_BIT, /* BIT STRING */
|
||||
ASN_OSUBV_STR, /* String types, not {BMP,Universal}String */
|
||||
ASN_OSUBV_U16, /* 16-bit character (BMPString) */
|
||||
ASN_OSUBV_U32 /* 32-bit character (UniversalString) */
|
||||
} subvariant;
|
||||
} asn_OCTET_STRING_specifics_t;
|
||||
|
||||
extern asn_OCTET_STRING_specifics_t asn_SPC_OCTET_STRING_specs;
|
||||
|
||||
size_t OCTET_STRING_random_length_constrained(
|
||||
const asn_TYPE_descriptor_t *, const asn_encoding_constraints_t *,
|
||||
size_t max_length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _OCTET_STRING_H_ */
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_DISABLE_OER_SUPPORT
|
||||
|
||||
#include <asn_internal.h>
|
||||
#include <OCTET_STRING.h>
|
||||
#include <errno.h>
|
||||
|
||||
asn_dec_rval_t
|
||||
OCTET_STRING_decode_oer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints, void **sptr,
|
||||
const void *ptr, size_t size) {
|
||||
const asn_OCTET_STRING_specifics_t *specs =
|
||||
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
|
||||
: &asn_SPC_OCTET_STRING_specs;
|
||||
OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
|
||||
const asn_oer_constraints_t *cts =
|
||||
constraints ? constraints : td->encoding_constraints.oer_constraints;
|
||||
ssize_t ct_size = cts ? cts->size : -1;
|
||||
asn_dec_rval_t rval = {RC_OK, 0};
|
||||
size_t expected_length = 0;
|
||||
|
||||
size_t unit_bytes;
|
||||
switch(specs->subvariant) {
|
||||
default:
|
||||
case ASN_OSUBV_BIT:
|
||||
ASN_DEBUG("Invalid use of OCTET STRING to decode BIT STRING");
|
||||
ASN__DECODE_FAILED;
|
||||
case ASN_OSUBV_ANY:
|
||||
/* Fall through */
|
||||
case ASN_OSUBV_STR:
|
||||
unit_bytes = 1;
|
||||
break;
|
||||
case ASN_OSUBV_U16:
|
||||
unit_bytes = 2;
|
||||
break;
|
||||
case ASN_OSUBV_U32:
|
||||
unit_bytes = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
(void)opt_codec_ctx;
|
||||
|
||||
if(!st) {
|
||||
st = (OCTET_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
|
||||
if(!st) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
if(ct_size >= 0) {
|
||||
expected_length = unit_bytes * ct_size;
|
||||
} else {
|
||||
/*
|
||||
* X.696 (08/2015) #27.2
|
||||
* Encode length determinant as _number of octets_, but only
|
||||
* if upper bound is not equal to lower bound.
|
||||
*/
|
||||
ssize_t len_len = oer_fetch_length(ptr, size, &expected_length);
|
||||
if(len_len > 0) {
|
||||
rval.consumed = len_len;
|
||||
ptr = (const char *)ptr + len_len;
|
||||
size -= len_len;
|
||||
} else if(len_len == 0) {
|
||||
ASN__DECODE_STARVED;
|
||||
} else if(len_len < 0) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
if(expected_length % unit_bytes != 0) {
|
||||
ASN_DEBUG(
|
||||
"Data size %" ASN_PRI_SIZE " bytes is not consistent with multiplier %" ASN_PRI_SIZE "",
|
||||
expected_length, unit_bytes);
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if(size < expected_length) {
|
||||
ASN__DECODE_STARVED;
|
||||
} else {
|
||||
uint8_t *buf = MALLOC(expected_length + 1);
|
||||
if(buf == NULL) {
|
||||
ASN__DECODE_FAILED;
|
||||
} else {
|
||||
memcpy(buf, ptr, expected_length);
|
||||
buf[expected_length] = '\0';
|
||||
}
|
||||
FREEMEM(st->buf);
|
||||
st->buf = buf;
|
||||
st->size = expected_length;
|
||||
|
||||
rval.consumed += expected_length;
|
||||
return rval;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode as Canonical OER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
OCTET_STRING_encode_oer(const asn_TYPE_descriptor_t *td,
|
||||
const asn_oer_constraints_t *constraints,
|
||||
const void *sptr, asn_app_consume_bytes_f *cb,
|
||||
void *app_key) {
|
||||
const asn_OCTET_STRING_specifics_t *specs =
|
||||
td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics
|
||||
: &asn_SPC_OCTET_STRING_specs;
|
||||
const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
|
||||
const asn_oer_constraints_t *cts =
|
||||
constraints ? constraints : td->encoding_constraints.oer_constraints;
|
||||
ssize_t ct_size = cts ? cts->size : -1;
|
||||
asn_enc_rval_t er = {0, 0, 0};
|
||||
|
||||
if(!st) ASN__ENCODE_FAILED;
|
||||
|
||||
ASN_DEBUG("Encoding %s %" ASN_PRI_SIZE " as OCTET STRING", td ? td->name : "", st->size);
|
||||
|
||||
if(ct_size >= 0) {
|
||||
/*
|
||||
* Check that available data matches the constraint
|
||||
*/
|
||||
size_t unit_bytes;
|
||||
switch(specs->subvariant) {
|
||||
default:
|
||||
case ASN_OSUBV_BIT:
|
||||
ASN_DEBUG("Invalid use of OCTET STRING to encode BIT STRING");
|
||||
ASN__ENCODE_FAILED;
|
||||
case ASN_OSUBV_ANY:
|
||||
/* Fall through */
|
||||
case ASN_OSUBV_STR:
|
||||
unit_bytes = 1;
|
||||
break;
|
||||
case ASN_OSUBV_U16:
|
||||
unit_bytes = 2;
|
||||
break;
|
||||
case ASN_OSUBV_U32:
|
||||
unit_bytes = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
if(st->size != unit_bytes * (size_t)ct_size) {
|
||||
ASN_DEBUG(
|
||||
"Trying to encode %s (%" ASN_PRI_SIZE " bytes) which doesn't fit SIZE "
|
||||
"constraint (%" ASN_PRI_SIZE ")",
|
||||
td->name, st->size, ct_size);
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* X.696 (08/2015) #27.2
|
||||
* Encode length determinant as _number of octets_, but only
|
||||
* if upper bound is not equal to lower bound.
|
||||
*/
|
||||
ssize_t ret = oer_serialize_length(st->size, cb, app_key);
|
||||
if(ret < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
er.encoded += ret;
|
||||
}
|
||||
|
||||
er.encoded += st->size;
|
||||
if(cb(st->buf, st->size, app_key) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
||||
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <OPEN_TYPE.h>
|
||||
#include <constr_CHOICE.h>
|
||||
#include <per_opentype.h>
|
||||
#include <errno.h>
|
||||
|
||||
asn_TYPE_operation_t asn_OP_OPEN_TYPE = {
|
||||
OPEN_TYPE_free,
|
||||
OPEN_TYPE_print,
|
||||
OPEN_TYPE_compare,
|
||||
OPEN_TYPE_decode_ber,
|
||||
OPEN_TYPE_encode_der,
|
||||
OPEN_TYPE_decode_xer,
|
||||
OPEN_TYPE_encode_xer,
|
||||
0, 0, /* No OER support, use "-gen-OER" to enable */
|
||||
#ifdef ASN_DISABLE_PER_SUPPORT
|
||||
0, 0,
|
||||
#else
|
||||
OPEN_TYPE_decode_uper,
|
||||
OPEN_TYPE_encode_uper,
|
||||
#endif
|
||||
0, /* Random fill is not supported for open type */
|
||||
0, /* Use generic outmost tag fetcher */
|
||||
};
|
||||
|
||||
#undef ADVANCE
|
||||
#define ADVANCE(num_bytes) \
|
||||
do { \
|
||||
size_t num = num_bytes; \
|
||||
ptr = ((const char *)ptr) + num; \
|
||||
size -= num; \
|
||||
consumed_myself += num; \
|
||||
} while(0)
|
||||
|
||||
asn_dec_rval_t
|
||||
OPEN_TYPE_ber_get(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void *sptr,
|
||||
const asn_TYPE_member_t *elm, const void *ptr, size_t size) {
|
||||
size_t consumed_myself = 0;
|
||||
asn_type_selector_result_t selected;
|
||||
void *memb_ptr; /* Pointer to the member */
|
||||
void **memb_ptr2; /* Pointer to that pointer */
|
||||
void *inner_value;
|
||||
asn_dec_rval_t rv;
|
||||
|
||||
if(!(elm->flags & ATF_OPEN_TYPE)) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
if(!elm->type_selector) {
|
||||
ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
|
||||
td->name, elm->name, elm->type->name);
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
selected = elm->type_selector(td, sptr);
|
||||
if(!selected.presence_index) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
/* Fetch the pointer to this member */
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
|
||||
} else {
|
||||
memb_ptr = (char *)sptr + elm->memb_offset;
|
||||
memb_ptr2 = &memb_ptr;
|
||||
}
|
||||
if(*memb_ptr2 != NULL) {
|
||||
/* Make sure we reset the structure first before encoding */
|
||||
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) != 0) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
inner_value =
|
||||
(char *)*memb_ptr2
|
||||
+ elm->type->elements[selected.presence_index - 1].memb_offset;
|
||||
|
||||
ASN_DEBUG("presence %d\n", selected.presence_index);
|
||||
|
||||
rv = selected.type_descriptor->op->ber_decoder(
|
||||
opt_codec_ctx, selected.type_descriptor, &inner_value, ptr, size,
|
||||
elm->tag_mode);
|
||||
ADVANCE(rv.consumed);
|
||||
rv.consumed = 0;
|
||||
switch(rv.code) {
|
||||
case RC_OK:
|
||||
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
|
||||
selected.presence_index)
|
||||
== 0) {
|
||||
rv.code = RC_OK;
|
||||
rv.consumed = consumed_myself;
|
||||
return rv;
|
||||
} else {
|
||||
/* Oh, now a full-blown failure failure */
|
||||
}
|
||||
/* Fall through */
|
||||
case RC_FAIL:
|
||||
rv.consumed = consumed_myself;
|
||||
/* Fall through */
|
||||
case RC_WMORE:
|
||||
break;
|
||||
}
|
||||
|
||||
if(*memb_ptr2) {
|
||||
const asn_CHOICE_specifics_t *specs =
|
||||
selected.type_descriptor->specifics;
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
|
||||
*memb_ptr2 = NULL;
|
||||
} else {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
|
||||
inner_value);
|
||||
memset(*memb_ptr2, 0, specs->struct_size);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
OPEN_TYPE_xer_get(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void *sptr,
|
||||
const asn_TYPE_member_t *elm, const void *ptr, size_t size) {
|
||||
size_t consumed_myself = 0;
|
||||
asn_type_selector_result_t selected;
|
||||
void *memb_ptr; /* Pointer to the member */
|
||||
void **memb_ptr2; /* Pointer to that pointer */
|
||||
void *inner_value;
|
||||
asn_dec_rval_t rv;
|
||||
|
||||
int xer_context = 0;
|
||||
ssize_t ch_size;
|
||||
pxer_chunk_type_e ch_type;
|
||||
|
||||
if(!(elm->flags & ATF_OPEN_TYPE)) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
if(!elm->type_selector) {
|
||||
ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
|
||||
td->name, elm->name, elm->type->name);
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
selected = elm->type_selector(td, sptr);
|
||||
if(!selected.presence_index) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
/* Fetch the pointer to this member */
|
||||
assert(elm->flags == ATF_OPEN_TYPE);
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
|
||||
} else {
|
||||
memb_ptr = (char *)sptr + elm->memb_offset;
|
||||
memb_ptr2 = &memb_ptr;
|
||||
}
|
||||
if(*memb_ptr2 != NULL) {
|
||||
/* Make sure we reset the structure first before encoding */
|
||||
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
|
||||
!= 0) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Confirm wrapper.
|
||||
*/
|
||||
for(;;) {
|
||||
ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
|
||||
if(ch_size < 0) {
|
||||
ASN__DECODE_FAILED;
|
||||
} else {
|
||||
switch(ch_type) {
|
||||
case PXER_WMORE:
|
||||
ASN__DECODE_STARVED;
|
||||
case PXER_COMMENT:
|
||||
case PXER_TEXT:
|
||||
ADVANCE(ch_size);
|
||||
continue;
|
||||
case PXER_TAG:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper value confirmed.
|
||||
*/
|
||||
switch(xer_check_tag(ptr, ch_size, elm->name)) {
|
||||
case XCT_OPENING:
|
||||
ADVANCE(ch_size);
|
||||
break;
|
||||
case XCT_BROKEN:
|
||||
default:
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
inner_value =
|
||||
(char *)*memb_ptr2
|
||||
+ elm->type->elements[selected.presence_index - 1].memb_offset;
|
||||
|
||||
rv = selected.type_descriptor->op->xer_decoder(
|
||||
opt_codec_ctx, selected.type_descriptor, &inner_value, NULL, ptr, size);
|
||||
ADVANCE(rv.consumed);
|
||||
rv.consumed = 0;
|
||||
switch(rv.code) {
|
||||
case RC_OK:
|
||||
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
|
||||
selected.presence_index)
|
||||
== 0) {
|
||||
break;
|
||||
} else {
|
||||
rv.code = RC_FAIL;
|
||||
}
|
||||
/* Fall through */
|
||||
case RC_FAIL:
|
||||
/* Point to a best position where failure occurred */
|
||||
rv.consumed = consumed_myself;
|
||||
/* Fall through */
|
||||
case RC_WMORE:
|
||||
/* Wrt. rv.consumed==0:
|
||||
* In case a genuine RC_WMORE, the whole Open Type decoding
|
||||
* will have to be restarted.
|
||||
*/
|
||||
if(*memb_ptr2) {
|
||||
const asn_CHOICE_specifics_t *specs =
|
||||
selected.type_descriptor->specifics;
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
|
||||
*memb_ptr2 = NULL;
|
||||
} else {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
|
||||
inner_value);
|
||||
memset(*memb_ptr2, 0, specs->struct_size);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finalize wrapper.
|
||||
*/
|
||||
for(;;) {
|
||||
ch_size = xer_next_token(&xer_context, ptr, size, &ch_type);
|
||||
if(ch_size < 0) {
|
||||
ASN__DECODE_FAILED;
|
||||
} else {
|
||||
switch(ch_type) {
|
||||
case PXER_WMORE:
|
||||
ASN__DECODE_STARVED;
|
||||
case PXER_COMMENT:
|
||||
case PXER_TEXT:
|
||||
ADVANCE(ch_size);
|
||||
continue;
|
||||
case PXER_TAG:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper value confirmed.
|
||||
*/
|
||||
switch(xer_check_tag(ptr, ch_size, elm->name)) {
|
||||
case XCT_CLOSING:
|
||||
ADVANCE(ch_size);
|
||||
break;
|
||||
case XCT_BROKEN:
|
||||
default:
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
rv.consumed += consumed_myself;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
#ifndef ASN_DISABLE_PER_SUPPORT
|
||||
|
||||
asn_dec_rval_t
|
||||
OPEN_TYPE_uper_get(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void *sptr,
|
||||
const asn_TYPE_member_t *elm, asn_per_data_t *pd) {
|
||||
asn_type_selector_result_t selected;
|
||||
void *memb_ptr; /* Pointer to the member */
|
||||
void **memb_ptr2; /* Pointer to that pointer */
|
||||
void *inner_value;
|
||||
asn_dec_rval_t rv;
|
||||
|
||||
if(!(elm->flags & ATF_OPEN_TYPE)) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
if(!elm->type_selector) {
|
||||
ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
|
||||
td->name, elm->name, elm->type->name);
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
selected = elm->type_selector(td, sptr);
|
||||
if(!selected.presence_index) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
/* Fetch the pointer to this member */
|
||||
assert(elm->flags == ATF_OPEN_TYPE);
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
|
||||
} else {
|
||||
memb_ptr = (char *)sptr + elm->memb_offset;
|
||||
memb_ptr2 = &memb_ptr;
|
||||
}
|
||||
if(*memb_ptr2 != NULL) {
|
||||
/* Make sure we reset the structure first before encoding */
|
||||
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0)
|
||||
!= 0) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
inner_value =
|
||||
(char *)*memb_ptr2
|
||||
+ elm->type->elements[selected.presence_index - 1].memb_offset;
|
||||
|
||||
rv = uper_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
|
||||
&inner_value, pd);
|
||||
switch(rv.code) {
|
||||
case RC_OK:
|
||||
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
|
||||
selected.presence_index)
|
||||
== 0) {
|
||||
break;
|
||||
} else {
|
||||
rv.code = RC_FAIL;
|
||||
}
|
||||
/* Fall through */
|
||||
case RC_WMORE:
|
||||
case RC_FAIL:
|
||||
if(*memb_ptr2) {
|
||||
const asn_CHOICE_specifics_t *specs =
|
||||
selected.type_descriptor->specifics;
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
|
||||
*memb_ptr2 = NULL;
|
||||
} else {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
|
||||
inner_value);
|
||||
memset(*memb_ptr2, 0, specs->struct_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
OPEN_TYPE_encode_uper(const asn_TYPE_descriptor_t *td,
|
||||
const asn_per_constraints_t *constraints,
|
||||
const void *sptr, asn_per_outp_t *po) {
|
||||
const void *memb_ptr; /* Pointer to the member */
|
||||
asn_TYPE_member_t *elm; /* CHOICE's element */
|
||||
asn_enc_rval_t er;
|
||||
unsigned present;
|
||||
|
||||
(void)constraints;
|
||||
|
||||
present = CHOICE_variant_get_presence(td, sptr);
|
||||
if(present == 0 || present > td->elements_count) {
|
||||
ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
present--;
|
||||
}
|
||||
|
||||
ASN_DEBUG("Encoding %s OPEN TYPE element %d", td->name, present);
|
||||
|
||||
elm = &td->elements[present];
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
/* Member is a pointer to another structure */
|
||||
memb_ptr =
|
||||
*(const void *const *)((const char *)sptr + elm->memb_offset);
|
||||
if(!memb_ptr) ASN__ENCODE_FAILED;
|
||||
} else {
|
||||
memb_ptr = (const char *)sptr + elm->memb_offset;
|
||||
}
|
||||
|
||||
if(uper_open_type_put(elm->type, NULL, memb_ptr, po) < 0) {
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
er.encoded = 0;
|
||||
ASN__ENCODED_OK(er);
|
||||
}
|
||||
|
||||
|
||||
#endif /* ASN_DISABLE_PER_SUPPORT */
|
||||
@@ -0,0 +1,63 @@
|
||||
/*-
|
||||
* Copyright (c) 2017-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_OPEN_TYPE_H
|
||||
#define ASN_OPEN_TYPE_H
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define OPEN_TYPE_free CHOICE_free
|
||||
#define OPEN_TYPE_print CHOICE_print
|
||||
#define OPEN_TYPE_compare CHOICE_compare
|
||||
#define OPEN_TYPE_constraint CHOICE_constraint
|
||||
#define OPEN_TYPE_decode_ber NULL
|
||||
#define OPEN_TYPE_encode_der CHOICE_encode_der
|
||||
#define OPEN_TYPE_decode_xer NULL
|
||||
#define OPEN_TYPE_encode_xer CHOICE_encode_xer
|
||||
#define OPEN_TYPE_decode_uper NULL
|
||||
|
||||
extern asn_TYPE_operation_t asn_OP_OPEN_TYPE;
|
||||
|
||||
/*
|
||||
* Decode an Open Type which is potentially constraiend
|
||||
* by the other members of the parent structure.
|
||||
*/
|
||||
asn_dec_rval_t OPEN_TYPE_ber_get(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *parent_type,
|
||||
void *parent_structure,
|
||||
const asn_TYPE_member_t *element,
|
||||
const void *ptr, size_t size);
|
||||
|
||||
asn_dec_rval_t OPEN_TYPE_xer_get(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *parent_type,
|
||||
void *parent_structure,
|
||||
const asn_TYPE_member_t *element,
|
||||
const void *ptr, size_t size);
|
||||
|
||||
asn_dec_rval_t OPEN_TYPE_oer_get(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *parent_type,
|
||||
void *parent_structure,
|
||||
asn_TYPE_member_t *element, const void *ptr,
|
||||
size_t size);
|
||||
|
||||
asn_dec_rval_t OPEN_TYPE_uper_get(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *parent_type,
|
||||
void *parent_structure,
|
||||
const asn_TYPE_member_t *element,
|
||||
asn_per_data_t *pd);
|
||||
|
||||
asn_enc_rval_t OPEN_TYPE_encode_uper(
|
||||
const asn_TYPE_descriptor_t *type_descriptor,
|
||||
const asn_per_constraints_t *constraints, const void *struct_ptr,
|
||||
asn_per_outp_t *per_output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ASN_OPEN_TYPE_H */
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <OPEN_TYPE.h>
|
||||
#include <constr_CHOICE.h>
|
||||
#include <errno.h>
|
||||
|
||||
asn_dec_rval_t
|
||||
OPEN_TYPE_oer_get(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void *sptr,
|
||||
asn_TYPE_member_t *elm, const void *ptr, size_t size) {
|
||||
asn_type_selector_result_t selected;
|
||||
void *memb_ptr; /* Pointer to the member */
|
||||
void **memb_ptr2; /* Pointer to that pointer */
|
||||
void *inner_value;
|
||||
asn_dec_rval_t rv;
|
||||
size_t ot_ret;
|
||||
|
||||
|
||||
if(!(elm->flags & ATF_OPEN_TYPE)) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
if(!elm->type_selector) {
|
||||
ASN_DEBUG("Type selector is not defined for Open Type %s->%s->%s",
|
||||
td->name, elm->name, elm->type->name);
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
selected = elm->type_selector(td, sptr);
|
||||
if(!selected.presence_index) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
/* Fetch the pointer to this member */
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
memb_ptr2 = (void **)((char *)sptr + elm->memb_offset);
|
||||
} else {
|
||||
memb_ptr = (char *)sptr + elm->memb_offset;
|
||||
memb_ptr2 = &memb_ptr;
|
||||
}
|
||||
if(*memb_ptr2 != NULL) {
|
||||
/* Make sure we reset the structure first before encoding */
|
||||
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2, 0) != 0) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
inner_value =
|
||||
(char *)*memb_ptr2
|
||||
+ elm->type->elements[selected.presence_index - 1].memb_offset;
|
||||
|
||||
ot_ret = oer_open_type_get(opt_codec_ctx, selected.type_descriptor, NULL,
|
||||
&inner_value, ptr, size);
|
||||
switch(ot_ret) {
|
||||
default:
|
||||
if(CHOICE_variant_set_presence(elm->type, *memb_ptr2,
|
||||
selected.presence_index)
|
||||
== 0) {
|
||||
rv.code = RC_OK;
|
||||
rv.consumed = ot_ret;
|
||||
return rv;
|
||||
} else {
|
||||
/* Oh, now a full-blown failure failure */
|
||||
}
|
||||
/* Fall through */
|
||||
case -1:
|
||||
rv.code = RC_FAIL;
|
||||
rv.consumed = ot_ret;
|
||||
break;
|
||||
case 0:
|
||||
rv.code = RC_WMORE;
|
||||
rv.consumed = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(*memb_ptr2) {
|
||||
const asn_CHOICE_specifics_t *specs =
|
||||
selected.type_descriptor->specifics;
|
||||
if(elm->flags & ATF_POINTER) {
|
||||
ASN_STRUCT_FREE(*selected.type_descriptor, inner_value);
|
||||
*memb_ptr2 = NULL;
|
||||
} else {
|
||||
ASN_STRUCT_FREE_CONTENTS_ONLY(*selected.type_descriptor,
|
||||
inner_value);
|
||||
memset(*memb_ptr2, 0, specs->struct_size);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "PAC.h"
|
||||
|
||||
/*
|
||||
* This type is implemented using BIT_STRING,
|
||||
* so here we adjust the DEF accordingly.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_PAC_tags_1[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (3 << 2))
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_PAC = {
|
||||
"PAC",
|
||||
"PAC",
|
||||
&asn_OP_BIT_STRING,
|
||||
asn_DEF_PAC_tags_1,
|
||||
sizeof(asn_DEF_PAC_tags_1)
|
||||
/sizeof(asn_DEF_PAC_tags_1[0]), /* 1 */
|
||||
asn_DEF_PAC_tags_1, /* Same as above */
|
||||
sizeof(asn_DEF_PAC_tags_1)
|
||||
/sizeof(asn_DEF_PAC_tags_1[0]), /* 1 */
|
||||
{ 0, 0, BIT_STRING_constraint },
|
||||
0, 0, /* No members */
|
||||
&asn_SPC_BIT_STRING_specs /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _PAC_H_
|
||||
#define _PAC_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include <BIT_STRING.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* PAC */
|
||||
typedef BIT_STRING_t PAC_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_PAC;
|
||||
asn_struct_free_f PAC_free;
|
||||
asn_struct_print_f PAC_print;
|
||||
asn_constr_check_f PAC_constraint;
|
||||
ber_type_decoder_f PAC_decode_ber;
|
||||
der_type_encoder_f PAC_encode_der;
|
||||
xer_type_decoder_f PAC_decode_xer;
|
||||
xer_type_encoder_f PAC_encode_xer;
|
||||
oer_type_decoder_f PAC_decode_oer;
|
||||
oer_type_encoder_f PAC_encode_oer;
|
||||
per_type_decoder_f PAC_decode_uper;
|
||||
per_type_encoder_f PAC_encode_uper;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PAC_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "Payload.h"
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_Payload_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
-1};
|
||||
static asn_per_constraints_t asn_PER_type_Payload_constr_1 CC_NOTUSED = {
|
||||
{ APC_CONSTRAINED, 2, 2, 0, 3 } /* (0..3) */,
|
||||
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
|
||||
0, 0 /* No PER value map */
|
||||
};
|
||||
static asn_TYPE_member_t asn_MBR_Payload_1[] = {
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct Payload, choice.samCommand),
|
||||
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
|
||||
+1, /* EXPLICIT tag at current level */
|
||||
&asn_DEF_SamCommand,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"samCommand"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct Payload, choice.nfcCommand),
|
||||
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
|
||||
+1, /* EXPLICIT tag at current level */
|
||||
&asn_DEF_NFCCommand,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"nfcCommand"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct Payload, choice.response),
|
||||
(ASN_TAG_CLASS_CONTEXT | (29 << 2)),
|
||||
+1, /* EXPLICIT tag at current level */
|
||||
&asn_DEF_Response,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"response"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct Payload, choice.errorResponse),
|
||||
(ASN_TAG_CLASS_CONTEXT | (30 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_ErrorResponse,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"errorResponse"
|
||||
},
|
||||
};
|
||||
static const asn_TYPE_tag2member_t asn_MAP_Payload_tag2el_1[] = {
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* samCommand */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* nfcCommand */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (29 << 2)), 2, 0, 0 }, /* response */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (30 << 2)), 3, 0, 0 } /* errorResponse */
|
||||
};
|
||||
static asn_CHOICE_specifics_t asn_SPC_Payload_specs_1 = {
|
||||
sizeof(struct Payload),
|
||||
offsetof(struct Payload, _asn_ctx),
|
||||
offsetof(struct Payload, present),
|
||||
sizeof(((struct Payload *)0)->present),
|
||||
asn_MAP_Payload_tag2el_1,
|
||||
4, /* Count of tags in the map */
|
||||
0, 0,
|
||||
-1 /* Extensions start */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_Payload = {
|
||||
"Payload",
|
||||
"Payload",
|
||||
&asn_OP_CHOICE,
|
||||
0, /* No effective tags (pointer) */
|
||||
0, /* No effective tags (count) */
|
||||
0, /* No tags (pointer) */
|
||||
0, /* No tags (count) */
|
||||
{ &asn_OER_type_Payload_constr_1, &asn_PER_type_Payload_constr_1, CHOICE_constraint },
|
||||
asn_MBR_Payload_1,
|
||||
4, /* Elements count */
|
||||
&asn_SPC_Payload_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _Payload_H_
|
||||
#define _Payload_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include "SamCommand.h"
|
||||
#include "NFCCommand.h"
|
||||
#include "Response.h"
|
||||
#include "ErrorResponse.h"
|
||||
#include <constr_CHOICE.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Dependencies */
|
||||
typedef enum Payload_PR {
|
||||
Payload_PR_NOTHING, /* No components present */
|
||||
Payload_PR_samCommand,
|
||||
Payload_PR_nfcCommand,
|
||||
Payload_PR_response,
|
||||
Payload_PR_errorResponse
|
||||
} Payload_PR;
|
||||
|
||||
/* Payload */
|
||||
typedef struct Payload {
|
||||
Payload_PR present;
|
||||
union Payload_u {
|
||||
SamCommand_t samCommand;
|
||||
NFCCommand_t nfcCommand;
|
||||
Response_t response;
|
||||
ErrorResponse_t errorResponse;
|
||||
} choice;
|
||||
|
||||
/* Context for parsing across buffer boundaries */
|
||||
asn_struct_ctx_t _asn_ctx;
|
||||
} Payload_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_Payload;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _Payload_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "Protocol.h"
|
||||
|
||||
/*
|
||||
* This type is implemented using OCTET_STRING,
|
||||
* so here we adjust the DEF accordingly.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_Protocol_tags_1[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_Protocol = {
|
||||
"Protocol",
|
||||
"Protocol",
|
||||
&asn_OP_OCTET_STRING,
|
||||
asn_DEF_Protocol_tags_1,
|
||||
sizeof(asn_DEF_Protocol_tags_1)
|
||||
/sizeof(asn_DEF_Protocol_tags_1[0]), /* 1 */
|
||||
asn_DEF_Protocol_tags_1, /* Same as above */
|
||||
sizeof(asn_DEF_Protocol_tags_1)
|
||||
/sizeof(asn_DEF_Protocol_tags_1[0]), /* 1 */
|
||||
{ 0, 0, OCTET_STRING_constraint },
|
||||
0, 0, /* No members */
|
||||
&asn_SPC_OCTET_STRING_specs /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _Protocol_H_
|
||||
#define _Protocol_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include <OCTET_STRING.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Protocol */
|
||||
typedef OCTET_STRING_t Protocol_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_Protocol;
|
||||
asn_struct_free_f Protocol_free;
|
||||
asn_struct_print_f Protocol_print;
|
||||
asn_constr_check_f Protocol_constraint;
|
||||
ber_type_decoder_f Protocol_decode_ber;
|
||||
der_type_encoder_f Protocol_encode_der;
|
||||
xer_type_decoder_f Protocol_decode_xer;
|
||||
xer_type_encoder_f Protocol_encode_xer;
|
||||
oer_type_decoder_f Protocol_decode_oer;
|
||||
oer_type_encoder_f Protocol_encode_oer;
|
||||
per_type_decoder_f Protocol_decode_uper;
|
||||
per_type_encoder_f Protocol_encode_uper;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _Protocol_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "RequestPacs.h"
|
||||
|
||||
asn_TYPE_member_t asn_MBR_RequestPacs_1[] = {
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct RequestPacs, contentElementTag),
|
||||
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_ContentElementTag,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"contentElementTag"
|
||||
},
|
||||
};
|
||||
static const ber_tlv_tag_t asn_DEF_RequestPacs_tags_1[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
|
||||
};
|
||||
static const asn_TYPE_tag2member_t asn_MAP_RequestPacs_tag2el_1[] = {
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 } /* contentElementTag */
|
||||
};
|
||||
asn_SEQUENCE_specifics_t asn_SPC_RequestPacs_specs_1 = {
|
||||
sizeof(struct RequestPacs),
|
||||
offsetof(struct RequestPacs, _asn_ctx),
|
||||
asn_MAP_RequestPacs_tag2el_1,
|
||||
1, /* Count of tags in the map */
|
||||
0, 0, 0, /* Optional elements (not needed) */
|
||||
-1, /* First extension addition */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_RequestPacs = {
|
||||
"RequestPacs",
|
||||
"RequestPacs",
|
||||
&asn_OP_SEQUENCE,
|
||||
asn_DEF_RequestPacs_tags_1,
|
||||
sizeof(asn_DEF_RequestPacs_tags_1)
|
||||
/sizeof(asn_DEF_RequestPacs_tags_1[0]), /* 1 */
|
||||
asn_DEF_RequestPacs_tags_1, /* Same as above */
|
||||
sizeof(asn_DEF_RequestPacs_tags_1)
|
||||
/sizeof(asn_DEF_RequestPacs_tags_1[0]), /* 1 */
|
||||
{ 0, 0, SEQUENCE_constraint },
|
||||
asn_MBR_RequestPacs_1,
|
||||
1, /* Elements count */
|
||||
&asn_SPC_RequestPacs_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _RequestPacs_H_
|
||||
#define _RequestPacs_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include "ContentElementTag.h"
|
||||
#include <constr_SEQUENCE.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* RequestPacs */
|
||||
typedef struct RequestPacs {
|
||||
ContentElementTag_t contentElementTag;
|
||||
|
||||
/* Context for parsing across buffer boundaries */
|
||||
asn_struct_ctx_t _asn_ctx;
|
||||
} RequestPacs_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_RequestPacs;
|
||||
extern asn_SEQUENCE_specifics_t asn_SPC_RequestPacs_specs_1;
|
||||
extern asn_TYPE_member_t asn_MBR_RequestPacs_1[1];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _RequestPacs_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "Response.h"
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_Response_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
-1};
|
||||
asn_per_constraints_t asn_PER_type_Response_constr_1 CC_NOTUSED = {
|
||||
{ APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */,
|
||||
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
|
||||
0, 0 /* No PER value map */
|
||||
};
|
||||
asn_TYPE_member_t asn_MBR_Response_1[] = {
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct Response, choice.nfcResponse),
|
||||
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
|
||||
+1, /* EXPLICIT tag at current level */
|
||||
&asn_DEF_NFCResponse,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"nfcResponse"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct Response, choice.samResponse),
|
||||
(ASN_TAG_CLASS_CONTEXT | (10 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_SamResponse,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"samResponse"
|
||||
},
|
||||
};
|
||||
static const asn_TYPE_tag2member_t asn_MAP_Response_tag2el_1[] = {
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* nfcResponse */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (10 << 2)), 1, 0, 0 } /* samResponse */
|
||||
};
|
||||
asn_CHOICE_specifics_t asn_SPC_Response_specs_1 = {
|
||||
sizeof(struct Response),
|
||||
offsetof(struct Response, _asn_ctx),
|
||||
offsetof(struct Response, present),
|
||||
sizeof(((struct Response *)0)->present),
|
||||
asn_MAP_Response_tag2el_1,
|
||||
2, /* Count of tags in the map */
|
||||
0, 0,
|
||||
-1 /* Extensions start */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_Response = {
|
||||
"Response",
|
||||
"Response",
|
||||
&asn_OP_CHOICE,
|
||||
0, /* No effective tags (pointer) */
|
||||
0, /* No effective tags (count) */
|
||||
0, /* No tags (pointer) */
|
||||
0, /* No tags (count) */
|
||||
{ &asn_OER_type_Response_constr_1, &asn_PER_type_Response_constr_1, CHOICE_constraint },
|
||||
asn_MBR_Response_1,
|
||||
2, /* Elements count */
|
||||
&asn_SPC_Response_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _Response_H_
|
||||
#define _Response_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include "NFCResponse.h"
|
||||
#include "SamResponse.h"
|
||||
#include <constr_CHOICE.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Dependencies */
|
||||
typedef enum Response_PR {
|
||||
Response_PR_NOTHING, /* No components present */
|
||||
Response_PR_nfcResponse,
|
||||
Response_PR_samResponse
|
||||
} Response_PR;
|
||||
|
||||
/* Response */
|
||||
typedef struct Response {
|
||||
Response_PR present;
|
||||
union Response_u {
|
||||
NFCResponse_t nfcResponse;
|
||||
SamResponse_t samResponse;
|
||||
} choice;
|
||||
|
||||
/* Context for parsing across buffer boundaries */
|
||||
asn_struct_ctx_t _asn_ctx;
|
||||
} Response_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_Response;
|
||||
extern asn_CHOICE_specifics_t asn_SPC_Response_specs_1;
|
||||
extern asn_TYPE_member_t asn_MBR_Response_1[2];
|
||||
extern asn_per_constraints_t asn_PER_type_Response_constr_1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _Response_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "RfStatus.h"
|
||||
|
||||
/*
|
||||
* This type is implemented using OCTET_STRING,
|
||||
* so here we adjust the DEF accordingly.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_RfStatus_tags_1[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_RfStatus = {
|
||||
"RfStatus",
|
||||
"RfStatus",
|
||||
&asn_OP_OCTET_STRING,
|
||||
asn_DEF_RfStatus_tags_1,
|
||||
sizeof(asn_DEF_RfStatus_tags_1)
|
||||
/sizeof(asn_DEF_RfStatus_tags_1[0]), /* 1 */
|
||||
asn_DEF_RfStatus_tags_1, /* Same as above */
|
||||
sizeof(asn_DEF_RfStatus_tags_1)
|
||||
/sizeof(asn_DEF_RfStatus_tags_1[0]), /* 1 */
|
||||
{ 0, 0, OCTET_STRING_constraint },
|
||||
0, 0, /* No members */
|
||||
&asn_SPC_OCTET_STRING_specs /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _RfStatus_H_
|
||||
#define _RfStatus_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include <OCTET_STRING.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* RfStatus */
|
||||
typedef OCTET_STRING_t RfStatus_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_RfStatus;
|
||||
asn_struct_free_f RfStatus_free;
|
||||
asn_struct_print_f RfStatus_print;
|
||||
asn_constr_check_f RfStatus_constraint;
|
||||
ber_type_decoder_f RfStatus_decode_ber;
|
||||
der_type_encoder_f RfStatus_encode_der;
|
||||
xer_type_decoder_f RfStatus_decode_xer;
|
||||
xer_type_encoder_f RfStatus_encode_xer;
|
||||
oer_type_decoder_f RfStatus_decode_oer;
|
||||
oer_type_encoder_f RfStatus_encode_oer;
|
||||
per_type_decoder_f RfStatus_decode_uper;
|
||||
per_type_encoder_f RfStatus_encode_uper;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _RfStatus_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "SamCommand.h"
|
||||
|
||||
static asn_oer_constraints_t asn_OER_type_SamCommand_constr_1 CC_NOTUSED = {
|
||||
{ 0, 0 },
|
||||
-1};
|
||||
asn_per_constraints_t asn_PER_type_SamCommand_constr_1 CC_NOTUSED = {
|
||||
{ APC_CONSTRAINED, 1, 1, 0, 1 } /* (0..1) */,
|
||||
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
|
||||
0, 0 /* No PER value map */
|
||||
};
|
||||
asn_TYPE_member_t asn_MBR_SamCommand_1[] = {
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct SamCommand, choice.requestPacs),
|
||||
(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_RequestPacs,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"requestPacs"
|
||||
},
|
||||
{ ATF_NOFLAGS, 0, offsetof(struct SamCommand, choice.cardDetected),
|
||||
(ASN_TAG_CLASS_CONTEXT | (13 << 2)),
|
||||
-1, /* IMPLICIT tag at current level */
|
||||
&asn_DEF_CardDetected,
|
||||
0,
|
||||
{ 0, 0, 0 },
|
||||
0, 0, /* No default value */
|
||||
"cardDetected"
|
||||
},
|
||||
};
|
||||
static const asn_TYPE_tag2member_t asn_MAP_SamCommand_tag2el_1[] = {
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 0 }, /* requestPacs */
|
||||
{ (ASN_TAG_CLASS_CONTEXT | (13 << 2)), 1, 0, 0 } /* cardDetected */
|
||||
};
|
||||
asn_CHOICE_specifics_t asn_SPC_SamCommand_specs_1 = {
|
||||
sizeof(struct SamCommand),
|
||||
offsetof(struct SamCommand, _asn_ctx),
|
||||
offsetof(struct SamCommand, present),
|
||||
sizeof(((struct SamCommand *)0)->present),
|
||||
asn_MAP_SamCommand_tag2el_1,
|
||||
2, /* Count of tags in the map */
|
||||
0, 0,
|
||||
-1 /* Extensions start */
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_SamCommand = {
|
||||
"SamCommand",
|
||||
"SamCommand",
|
||||
&asn_OP_CHOICE,
|
||||
0, /* No effective tags (pointer) */
|
||||
0, /* No effective tags (count) */
|
||||
0, /* No tags (pointer) */
|
||||
0, /* No tags (count) */
|
||||
{ &asn_OER_type_SamCommand_constr_1, &asn_PER_type_SamCommand_constr_1, CHOICE_constraint },
|
||||
asn_MBR_SamCommand_1,
|
||||
2, /* Elements count */
|
||||
&asn_SPC_SamCommand_specs_1 /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _SamCommand_H_
|
||||
#define _SamCommand_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include "RequestPacs.h"
|
||||
#include "CardDetected.h"
|
||||
#include <constr_CHOICE.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Dependencies */
|
||||
typedef enum SamCommand_PR {
|
||||
SamCommand_PR_NOTHING, /* No components present */
|
||||
SamCommand_PR_requestPacs,
|
||||
SamCommand_PR_cardDetected
|
||||
} SamCommand_PR;
|
||||
|
||||
/* SamCommand */
|
||||
typedef struct SamCommand {
|
||||
SamCommand_PR present;
|
||||
union SamCommand_u {
|
||||
RequestPacs_t requestPacs;
|
||||
CardDetected_t cardDetected;
|
||||
} choice;
|
||||
|
||||
/* Context for parsing across buffer boundaries */
|
||||
asn_struct_ctx_t _asn_ctx;
|
||||
} SamCommand_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_SamCommand;
|
||||
extern asn_CHOICE_specifics_t asn_SPC_SamCommand_specs_1;
|
||||
extern asn_TYPE_member_t asn_MBR_SamCommand_1[2];
|
||||
extern asn_per_constraints_t asn_PER_type_SamCommand_constr_1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SamCommand_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#include "SamResponse.h"
|
||||
|
||||
/*
|
||||
* This type is implemented using OCTET_STRING,
|
||||
* so here we adjust the DEF accordingly.
|
||||
*/
|
||||
static const ber_tlv_tag_t asn_DEF_SamResponse_tags_1[] = {
|
||||
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
|
||||
};
|
||||
asn_TYPE_descriptor_t asn_DEF_SamResponse = {
|
||||
"SamResponse",
|
||||
"SamResponse",
|
||||
&asn_OP_OCTET_STRING,
|
||||
asn_DEF_SamResponse_tags_1,
|
||||
sizeof(asn_DEF_SamResponse_tags_1)
|
||||
/sizeof(asn_DEF_SamResponse_tags_1[0]), /* 1 */
|
||||
asn_DEF_SamResponse_tags_1, /* Same as above */
|
||||
sizeof(asn_DEF_SamResponse_tags_1)
|
||||
/sizeof(asn_DEF_SamResponse_tags_1[0]), /* 1 */
|
||||
{ 0, 0, OCTET_STRING_constraint },
|
||||
0, 0, /* No members */
|
||||
&asn_SPC_OCTET_STRING_specs /* Additional specs */
|
||||
};
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Generated by asn1c-0.9.29 (http://lionet.info/asn1c)
|
||||
* From ASN.1 module "Seader"
|
||||
* found in "applications_user/seader/seader.asn1"
|
||||
* `asn1c -D applications_user/seader/lib/asn1 -no-gen-example -pdu=all`
|
||||
*/
|
||||
|
||||
#ifndef _SamResponse_H_
|
||||
#define _SamResponse_H_
|
||||
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
/* Including external dependencies */
|
||||
#include <OCTET_STRING.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* SamResponse */
|
||||
typedef OCTET_STRING_t SamResponse_t;
|
||||
|
||||
/* Implementation */
|
||||
extern asn_TYPE_descriptor_t asn_DEF_SamResponse;
|
||||
asn_struct_free_f SamResponse_free;
|
||||
asn_struct_print_f SamResponse_print;
|
||||
asn_constr_check_f SamResponse_constraint;
|
||||
ber_type_decoder_f SamResponse_decode_ber;
|
||||
der_type_encoder_f SamResponse_encode_der;
|
||||
xer_type_decoder_f SamResponse_decode_xer;
|
||||
xer_type_encoder_f SamResponse_encode_xer;
|
||||
oer_type_decoder_f SamResponse_decode_oer;
|
||||
oer_type_encoder_f SamResponse_encode_oer;
|
||||
per_type_decoder_f SamResponse_decode_uper;
|
||||
per_type_encoder_f SamResponse_encode_uper;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SamResponse_H_ */
|
||||
#include <asn_internal.h>
|
||||
@@ -0,0 +1,440 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <asn_application.h>
|
||||
#include <errno.h>
|
||||
|
||||
static asn_enc_rval_t asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
enum asn_transfer_syntax syntax,
|
||||
const asn_TYPE_descriptor_t *td,
|
||||
const void *sptr,
|
||||
asn_app_consume_bytes_f *callback,
|
||||
void *callback_key);
|
||||
|
||||
|
||||
struct callback_count_bytes_key {
|
||||
asn_app_consume_bytes_f *callback;
|
||||
void *callback_key;
|
||||
size_t computed_size;
|
||||
};
|
||||
|
||||
/*
|
||||
* Encoder which just counts bytes that come through it.
|
||||
*/
|
||||
static int
|
||||
callback_count_bytes_cb(const void *data, size_t size, void *keyp) {
|
||||
struct callback_count_bytes_key *key = keyp;
|
||||
int ret;
|
||||
|
||||
ret = key->callback(data, size, key->callback_key);
|
||||
if(ret >= 0) {
|
||||
key->computed_size += size;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct overrun_encoder_key {
|
||||
void *buffer;
|
||||
size_t buffer_size;
|
||||
size_t computed_size;
|
||||
};
|
||||
|
||||
struct dynamic_encoder_key {
|
||||
void *buffer;
|
||||
size_t buffer_size;
|
||||
size_t computed_size;
|
||||
};
|
||||
|
||||
struct callback_failure_catch_key {
|
||||
asn_app_consume_bytes_f *callback;
|
||||
void *callback_key;
|
||||
int callback_failed;
|
||||
};
|
||||
|
||||
/*
|
||||
* Encoder which doesn't stop counting bytes
|
||||
* even if it reaches the end of the buffer.
|
||||
*/
|
||||
static int
|
||||
overrun_encoder_cb(const void *data, size_t size, void *keyp) {
|
||||
struct overrun_encoder_key *key = keyp;
|
||||
|
||||
if(key->computed_size + size > key->buffer_size) {
|
||||
/*
|
||||
* Avoid accident on the next call:
|
||||
* stop adding bytes to the buffer.
|
||||
*/
|
||||
key->buffer_size = 0;
|
||||
} else {
|
||||
memcpy((char *)key->buffer + key->computed_size, data, size);
|
||||
}
|
||||
key->computed_size += size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encoder which dynamically allocates output, and continues
|
||||
* to count even if allocation failed.
|
||||
*/
|
||||
static int
|
||||
dynamic_encoder_cb(const void *data, size_t size, void *keyp) {
|
||||
struct dynamic_encoder_key *key = keyp;
|
||||
|
||||
if(key->buffer) {
|
||||
if(key->computed_size + size >= key->buffer_size) {
|
||||
void *p;
|
||||
size_t new_size = key->buffer_size;
|
||||
|
||||
do {
|
||||
new_size *= 2;
|
||||
} while(new_size <= key->computed_size + size);
|
||||
|
||||
p = REALLOC(key->buffer, new_size);
|
||||
if(p) {
|
||||
key->buffer = p;
|
||||
key->buffer_size = new_size;
|
||||
} else {
|
||||
FREEMEM(key->buffer);
|
||||
key->buffer = 0;
|
||||
key->buffer_size = 0;
|
||||
key->computed_size += size;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
memcpy((char *)key->buffer + key->computed_size, data, size);
|
||||
}
|
||||
|
||||
key->computed_size += size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encoder which help convert the application level encoder failure into EIO.
|
||||
*/
|
||||
static int
|
||||
callback_failure_catch_cb(const void *data, size_t size, void *keyp) {
|
||||
struct callback_failure_catch_key *key = keyp;
|
||||
int ret;
|
||||
|
||||
ret = key->callback(data, size, key->callback_key);
|
||||
if(ret < 0) {
|
||||
key->callback_failed = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
asn_encode(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,
|
||||
const void *sptr, asn_app_consume_bytes_f *callback, void *callback_key) {
|
||||
struct callback_failure_catch_key cb_key;
|
||||
asn_enc_rval_t er;
|
||||
|
||||
if(!callback) {
|
||||
errno = EINVAL;
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
cb_key.callback = callback;
|
||||
cb_key.callback_key = callback_key;
|
||||
cb_key.callback_failed = 0;
|
||||
|
||||
er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
|
||||
callback_failure_catch_cb, &cb_key);
|
||||
if(cb_key.callback_failed) {
|
||||
assert(er.encoded == -1);
|
||||
assert(errno == EBADF);
|
||||
errno = EIO;
|
||||
}
|
||||
|
||||
return er;
|
||||
}
|
||||
|
||||
asn_enc_rval_t
|
||||
asn_encode_to_buffer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
enum asn_transfer_syntax syntax,
|
||||
const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
void *buffer, size_t buffer_size) {
|
||||
struct overrun_encoder_key buf_key;
|
||||
asn_enc_rval_t er;
|
||||
|
||||
if(buffer_size > 0 && !buffer) {
|
||||
errno = EINVAL;
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
buf_key.buffer = buffer;
|
||||
buf_key.buffer_size = buffer_size;
|
||||
buf_key.computed_size = 0;
|
||||
|
||||
er = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
|
||||
overrun_encoder_cb, &buf_key);
|
||||
|
||||
if(er.encoded >= 0 && (size_t)er.encoded != buf_key.computed_size) {
|
||||
ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
|
||||
" yet produced %" ASN_PRI_SIZE " bytes",
|
||||
er.encoded, buf_key.computed_size);
|
||||
assert(er.encoded < 0 || (size_t)er.encoded == buf_key.computed_size);
|
||||
}
|
||||
|
||||
return er;
|
||||
}
|
||||
|
||||
asn_encode_to_new_buffer_result_t
|
||||
asn_encode_to_new_buffer(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
enum asn_transfer_syntax syntax,
|
||||
const asn_TYPE_descriptor_t *td, const void *sptr) {
|
||||
struct dynamic_encoder_key buf_key;
|
||||
asn_encode_to_new_buffer_result_t res;
|
||||
|
||||
buf_key.buffer_size = 16;
|
||||
buf_key.buffer = MALLOC(buf_key.buffer_size);
|
||||
buf_key.computed_size = 0;
|
||||
|
||||
res.result = asn_encode_internal(opt_codec_ctx, syntax, td, sptr,
|
||||
dynamic_encoder_cb, &buf_key);
|
||||
|
||||
if(res.result.encoded >= 0
|
||||
&& (size_t)res.result.encoded != buf_key.computed_size) {
|
||||
ASN_DEBUG("asn_encode() returned %" ASN_PRI_SSIZE
|
||||
" yet produced %" ASN_PRI_SIZE " bytes",
|
||||
res.result.encoded, buf_key.computed_size);
|
||||
assert(res.result.encoded < 0
|
||||
|| (size_t)res.result.encoded == buf_key.computed_size);
|
||||
}
|
||||
|
||||
res.buffer = buf_key.buffer;
|
||||
|
||||
/* 0-terminate just in case. */
|
||||
if(res.buffer) {
|
||||
assert(buf_key.computed_size < buf_key.buffer_size);
|
||||
((char *)res.buffer)[buf_key.computed_size] = '\0';
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static asn_enc_rval_t
|
||||
asn_encode_internal(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
enum asn_transfer_syntax syntax,
|
||||
const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
asn_app_consume_bytes_f *callback, void *callback_key) {
|
||||
asn_enc_rval_t er;
|
||||
enum xer_encoder_flags_e xer_flags = XER_F_CANONICAL;
|
||||
|
||||
(void)opt_codec_ctx; /* Parameters are not checked on encode yet. */
|
||||
|
||||
if(!td || !sptr) {
|
||||
errno = EINVAL;
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
switch(syntax) {
|
||||
case ATS_NONSTANDARD_PLAINTEXT:
|
||||
if(td->op->print_struct) {
|
||||
struct callback_count_bytes_key cb_key;
|
||||
cb_key.callback = callback;
|
||||
cb_key.callback_key = callback_key;
|
||||
cb_key.computed_size = 0;
|
||||
if(td->op->print_struct(td, sptr, 1, callback_count_bytes_cb,
|
||||
&cb_key)
|
||||
< 0
|
||||
|| callback_count_bytes_cb("\n", 1, &cb_key) < 0) {
|
||||
errno = EBADF; /* Structure has incorrect form. */
|
||||
er.encoded = -1;
|
||||
er.failed_type = td;
|
||||
er.structure_ptr = sptr;
|
||||
} else {
|
||||
er.encoded = cb_key.computed_size;
|
||||
er.failed_type = 0;
|
||||
er.structure_ptr = 0;
|
||||
}
|
||||
} else {
|
||||
errno = ENOENT; /* Transfer syntax is not defined for this type. */
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
break;
|
||||
|
||||
case ATS_RANDOM:
|
||||
errno = ENOENT; /* Randomization doesn't make sense on output. */
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
case ATS_BER:
|
||||
/* BER is a superset of DER. */
|
||||
/* Fall through. */
|
||||
case ATS_DER:
|
||||
if(td->op->der_encoder) {
|
||||
er = der_encode(td, sptr, callback, callback_key);
|
||||
if(er.encoded == -1) {
|
||||
if(er.failed_type && er.failed_type->op->der_encoder) {
|
||||
errno = EBADF; /* Structure has incorrect form. */
|
||||
} else {
|
||||
errno = ENOENT; /* DER is not defined for this type. */
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errno = ENOENT; /* Transfer syntax is not defined for this type. */
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
break;
|
||||
case ATS_CER:
|
||||
errno = ENOENT; /* Transfer syntax is not defined for any type. */
|
||||
ASN__ENCODE_FAILED;
|
||||
|
||||
#ifdef ASN_DISABLE_OER_SUPPORT
|
||||
case ATS_BASIC_OER:
|
||||
case ATS_CANONICAL_OER:
|
||||
errno = ENOENT; /* PER is not defined. */
|
||||
ASN__ENCODE_FAILED;
|
||||
break;
|
||||
#else /* ASN_DISABLE_OER_SUPPORT */
|
||||
case ATS_BASIC_OER:
|
||||
/* CANONICAL-OER is a superset of BASIC-OER. */
|
||||
/* Fall through. */
|
||||
case ATS_CANONICAL_OER:
|
||||
if(td->op->oer_encoder) {
|
||||
er = oer_encode(td, sptr, callback, callback_key);
|
||||
if(er.encoded == -1) {
|
||||
if(er.failed_type && er.failed_type->op->oer_encoder) {
|
||||
errno = EBADF; /* Structure has incorrect form. */
|
||||
} else {
|
||||
errno = ENOENT; /* OER is not defined for this type. */
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errno = ENOENT; /* Transfer syntax is not defined for this type. */
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
break;
|
||||
#endif /* ASN_DISABLE_OER_SUPPORT */
|
||||
|
||||
#ifdef ASN_DISABLE_PER_SUPPORT
|
||||
case ATS_UNALIGNED_BASIC_PER:
|
||||
case ATS_UNALIGNED_CANONICAL_PER:
|
||||
errno = ENOENT; /* PER is not defined. */
|
||||
ASN__ENCODE_FAILED;
|
||||
break;
|
||||
#else /* ASN_DISABLE_PER_SUPPORT */
|
||||
case ATS_UNALIGNED_BASIC_PER:
|
||||
/* CANONICAL-UPER is a superset of BASIC-UPER. */
|
||||
/* Fall through. */
|
||||
case ATS_UNALIGNED_CANONICAL_PER:
|
||||
if(td->op->uper_encoder) {
|
||||
er = uper_encode(td, 0, sptr, callback, callback_key);
|
||||
if(er.encoded == -1) {
|
||||
if(er.failed_type && er.failed_type->op->uper_encoder) {
|
||||
errno = EBADF; /* Structure has incorrect form. */
|
||||
} else {
|
||||
errno = ENOENT; /* UPER is not defined for this type. */
|
||||
}
|
||||
} else {
|
||||
ASN_DEBUG("Complete encoded in %ld bits", (long)er.encoded);
|
||||
if(er.encoded == 0) {
|
||||
/* Enforce "Complete Encoding" of X.691 #11.1 */
|
||||
if(callback("\0", 1, callback_key) < 0) {
|
||||
errno = EBADF;
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
er.encoded = 8; /* Exactly 8 zero bits is added. */
|
||||
}
|
||||
/* Convert bits into bytes */
|
||||
er.encoded = (er.encoded + 7) >> 3;
|
||||
}
|
||||
} else {
|
||||
errno = ENOENT; /* Transfer syntax is not defined for this type. */
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
break;
|
||||
#endif /* ASN_DISABLE_PER_SUPPORT */
|
||||
|
||||
case ATS_BASIC_XER:
|
||||
/* CANONICAL-XER is a superset of BASIC-XER. */
|
||||
xer_flags &= ~XER_F_CANONICAL;
|
||||
xer_flags |= XER_F_BASIC;
|
||||
/* Fall through. */
|
||||
case ATS_CANONICAL_XER:
|
||||
if(td->op->xer_encoder) {
|
||||
er = xer_encode(td, sptr, xer_flags, callback, callback_key);
|
||||
if(er.encoded == -1) {
|
||||
if(er.failed_type && er.failed_type->op->xer_encoder) {
|
||||
errno = EBADF; /* Structure has incorrect form. */
|
||||
} else {
|
||||
errno = ENOENT; /* XER is not defined for this type. */
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errno = ENOENT; /* Transfer syntax is not defined for this type. */
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = ENOENT;
|
||||
ASN__ENCODE_FAILED;
|
||||
}
|
||||
|
||||
return er;
|
||||
}
|
||||
|
||||
asn_dec_rval_t
|
||||
asn_decode(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
enum asn_transfer_syntax syntax, const asn_TYPE_descriptor_t *td,
|
||||
void **sptr, const void *buffer, size_t size) {
|
||||
if(!td || !td->op || !sptr || (size && !buffer)) {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
switch(syntax) {
|
||||
case ATS_CER:
|
||||
case ATS_NONSTANDARD_PLAINTEXT:
|
||||
default:
|
||||
errno = ENOENT;
|
||||
ASN__DECODE_FAILED;
|
||||
|
||||
case ATS_RANDOM:
|
||||
if(!td->op->random_fill) {
|
||||
ASN__DECODE_FAILED;
|
||||
} else {
|
||||
if(asn_random_fill(td, sptr, 16000) == 0) {
|
||||
asn_dec_rval_t ret = {RC_OK, 0};
|
||||
return ret;
|
||||
} else {
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ATS_DER:
|
||||
case ATS_BER:
|
||||
return ber_decode(opt_codec_ctx, td, sptr, buffer, size);
|
||||
|
||||
case ATS_BASIC_OER:
|
||||
case ATS_CANONICAL_OER:
|
||||
#ifdef ASN_DISABLE_OER_SUPPORT
|
||||
errno = ENOENT;
|
||||
ASN__DECODE_FAILED;
|
||||
#else
|
||||
return oer_decode(opt_codec_ctx, td, sptr, buffer, size);
|
||||
#endif
|
||||
|
||||
case ATS_UNALIGNED_BASIC_PER:
|
||||
case ATS_UNALIGNED_CANONICAL_PER:
|
||||
#ifdef ASN_DISABLE_PER_SUPPORT
|
||||
errno = ENOENT;
|
||||
ASN__DECODE_FAILED;
|
||||
#else
|
||||
return uper_decode_complete(opt_codec_ctx, td, sptr, buffer, size);
|
||||
#endif
|
||||
|
||||
case ATS_BASIC_XER:
|
||||
case ATS_CANONICAL_XER:
|
||||
return xer_decode(opt_codec_ctx, td, sptr, buffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/*-
|
||||
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* Application-level ASN.1 callbacks.
|
||||
*/
|
||||
#ifndef ASN_APPLICATION_H
|
||||
#define ASN_APPLICATION_H
|
||||
|
||||
#include "asn_system.h" /* for platform-dependent types */
|
||||
#include "asn_codecs.h" /* for ASN.1 codecs specifics */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A selection of ASN.1 Transfer Syntaxes to use with generalized
|
||||
* encoders and decoders declared further in this .h file.
|
||||
*/
|
||||
enum asn_transfer_syntax {
|
||||
/* Avoid appearance of a default transfer syntax. */
|
||||
ATS_INVALID = 0,
|
||||
/* Plaintext output (not conforming to any standard), for debugging. */
|
||||
ATS_NONSTANDARD_PLAINTEXT,
|
||||
/* Returns a randomly generatede structure. */
|
||||
ATS_RANDOM,
|
||||
/*
|
||||
* X.690:
|
||||
* BER: Basic Encoding Rules.
|
||||
* DER: Distinguished Encoding Rules.
|
||||
* CER: Canonical Encoding Rules.
|
||||
* DER and CER are more strict variants of BER.
|
||||
*/
|
||||
ATS_BER,
|
||||
ATS_DER,
|
||||
ATS_CER, /* Only decoding is supported */
|
||||
/*
|
||||
* X.696:
|
||||
* OER: Octet Encoding Rules.
|
||||
* CANONICAL-OER is a more strict variant of BASIC-OER.
|
||||
*/
|
||||
ATS_BASIC_OER,
|
||||
ATS_CANONICAL_OER,
|
||||
/*
|
||||
* X.691:
|
||||
* PER: Packed Encoding Rules.
|
||||
* CANONICAL-PER is a more strict variant of BASIC-PER.
|
||||
* NOTE: Produces or consumes a complete encoding (X.691 (08/2015) #11.1).
|
||||
*/
|
||||
ATS_UNALIGNED_BASIC_PER,
|
||||
ATS_UNALIGNED_CANONICAL_PER,
|
||||
/*
|
||||
* X.693:
|
||||
* XER: XML Encoding Rules.
|
||||
* CANONICAL-XER is a more strict variant of BASIC-XER.
|
||||
*/
|
||||
ATS_BASIC_XER,
|
||||
ATS_CANONICAL_XER
|
||||
};
|
||||
|
||||
/*
|
||||
* A generic encoder for any supported transfer syntax.
|
||||
* RETURN VALUES:
|
||||
* The (.encoded) field of the return value is REDEFINED to mean the following:
|
||||
* >=0: The computed size of the encoded data. Can exceed the (buffer_size).
|
||||
* -1: Error encoding the structure. See the error code in (errno):
|
||||
* EINVAL: Incorrect parameters to the function, such as NULLs.
|
||||
* ENOENT: Encoding transfer syntax is not defined (for this type).
|
||||
* EBADF: The structure has invalid form or content constraint failed.
|
||||
* The (.failed_type) and (.structure_ptr) MIGHT be set to the appropriate
|
||||
* values at the place of failure, if at all possible.
|
||||
* WARNING: The (.encoded) field of the return value can exceed the buffer_size.
|
||||
* This is similar to snprintf(3) contract which might return values
|
||||
* greater than the buffer size.
|
||||
*/
|
||||
asn_enc_rval_t asn_encode_to_buffer(
|
||||
const asn_codec_ctx_t *opt_codec_parameters, /* See asn_codecs.h */
|
||||
enum asn_transfer_syntax,
|
||||
const struct asn_TYPE_descriptor_s *type_to_encode,
|
||||
const void *structure_to_encode, void *buffer, size_t buffer_size);
|
||||
|
||||
/*
|
||||
* A variant of asn_encode_to_buffer() with automatically allocated buffer.
|
||||
* RETURN VALUES:
|
||||
* On success, returns a newly allocated (.buffer) containing the whole message.
|
||||
* The message size is returned in (.result.encoded).
|
||||
* On failure:
|
||||
* (.buffer) is NULL,
|
||||
* (.result.encoded) as in asn_encode_to_buffer(),
|
||||
* The errno codes as in asn_encode_to_buffer(), plus the following:
|
||||
* ENOMEM: Memory allocation failed due to system or internal limits.
|
||||
* The user is responsible for freeing the (.buffer).
|
||||
*/
|
||||
typedef struct asn_encode_to_new_buffer_result_s {
|
||||
void *buffer; /* NULL if failed to encode. */
|
||||
asn_enc_rval_t result;
|
||||
} asn_encode_to_new_buffer_result_t;
|
||||
asn_encode_to_new_buffer_result_t asn_encode_to_new_buffer(
|
||||
const asn_codec_ctx_t *opt_codec_parameters, /* See asn_codecs.h */
|
||||
enum asn_transfer_syntax,
|
||||
const struct asn_TYPE_descriptor_s *type_to_encode,
|
||||
const void *structure_to_encode);
|
||||
|
||||
|
||||
/*
|
||||
* Generic type of an application-defined callback to return various
|
||||
* types of data to the application.
|
||||
* EXPECTED RETURN VALUES:
|
||||
* -1: Failed to consume bytes. Abort the mission.
|
||||
* Non-negative return values indicate success, and ignored.
|
||||
*/
|
||||
typedef int(asn_app_consume_bytes_f)(const void *buffer, size_t size,
|
||||
void *application_specific_key);
|
||||
|
||||
|
||||
/*
|
||||
* A generic encoder for any supported transfer syntax.
|
||||
* Returns the comprehensive encoding result descriptor (see asn_codecs.h).
|
||||
* RETURN VALUES:
|
||||
* The negative (.encoded) field of the return values is accompanied with the
|
||||
* following error codes (errno):
|
||||
* EINVAL: Incorrect parameters to the function, such as NULLs.
|
||||
* ENOENT: Encoding transfer syntax is not defined (for this type).
|
||||
* EBADF: The structure has invalid form or content constraint failed.
|
||||
* EIO: The (callback) has returned negative value during encoding.
|
||||
*/
|
||||
asn_enc_rval_t asn_encode(
|
||||
const asn_codec_ctx_t *opt_codec_parameters, /* See asn_codecs.h */
|
||||
enum asn_transfer_syntax,
|
||||
const struct asn_TYPE_descriptor_s *type_to_encode,
|
||||
const void *structure_to_encode,
|
||||
asn_app_consume_bytes_f *callback, void *callback_key);
|
||||
|
||||
|
||||
/*
|
||||
* A generic decoder for any supported transfer syntax.
|
||||
*/
|
||||
asn_dec_rval_t asn_decode(
|
||||
const asn_codec_ctx_t *opt_codec_parameters, enum asn_transfer_syntax,
|
||||
const struct asn_TYPE_descriptor_s *type_to_decode,
|
||||
void **structure_ptr, /* Pointer to a target structure's pointer */
|
||||
const void *buffer, /* Data to be decoded */
|
||||
size_t size /* Size of that buffer */
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* A callback of this type is called whenever constraint validation fails
|
||||
* on some ASN.1 type. See "constraints.h" for more details on constraint
|
||||
* validation.
|
||||
* This callback specifies a descriptor of the ASN.1 type which failed
|
||||
* the constraint check, as well as human readable message on what
|
||||
* particular constraint has failed.
|
||||
*/
|
||||
typedef void (asn_app_constraint_failed_f)(void *application_specific_key,
|
||||
const struct asn_TYPE_descriptor_s *type_descriptor_which_failed,
|
||||
const void *structure_which_failed_ptr,
|
||||
const char *error_message_format, ...) CC_PRINTFLIKE(4, 5);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "constr_TYPE.h" /* for asn_TYPE_descriptor_t */
|
||||
|
||||
#endif /* ASN_APPLICATION_H */
|
||||
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_system.h>
|
||||
#include <asn_internal.h>
|
||||
#include <asn_bit_data.h>
|
||||
|
||||
/*
|
||||
* Create a contiguous non-refillable bit data structure.
|
||||
* Can be freed by FREEMEM().
|
||||
*/
|
||||
asn_bit_data_t *
|
||||
asn_bit_data_new_contiguous(const void *data, size_t size_bits) {
|
||||
size_t size_bytes = (size_bits + 7) / 8;
|
||||
asn_bit_data_t *pd;
|
||||
uint8_t *bytes;
|
||||
|
||||
/* Get the extensions map */
|
||||
pd = CALLOC(1, sizeof(*pd) + size_bytes + 1);
|
||||
if(!pd) {
|
||||
return NULL;
|
||||
}
|
||||
bytes = (void *)(((char *)pd) + sizeof(*pd));
|
||||
memcpy(bytes, data, size_bytes);
|
||||
bytes[size_bytes] = 0;
|
||||
pd->buffer = bytes;
|
||||
pd->nboff = 0;
|
||||
pd->nbits = size_bits;
|
||||
|
||||
return pd;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
asn_bit_data_string(asn_bit_data_t *pd) {
|
||||
static char buf[2][32];
|
||||
static int n;
|
||||
n = (n+1) % 2;
|
||||
snprintf(buf[n], sizeof(buf[n]),
|
||||
"{m=%" ASN_PRI_SIZE " span %" ASN_PRI_SIZE "[%" ASN_PRI_SIZE
|
||||
"..%" ASN_PRI_SIZE "] (%" ASN_PRI_SIZE ")}",
|
||||
pd->moved, ((uintptr_t)(pd->buffer) & 0xf), pd->nboff, pd->nbits,
|
||||
pd->nbits - pd->nboff);
|
||||
return buf[n];
|
||||
}
|
||||
|
||||
void
|
||||
asn_get_undo(asn_bit_data_t *pd, int nbits) {
|
||||
if((ssize_t)pd->nboff < nbits) {
|
||||
assert((ssize_t)pd->nboff < nbits);
|
||||
} else {
|
||||
pd->nboff -= nbits;
|
||||
pd->moved -= nbits;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract a small number of bits (<= 31) from the specified PER data pointer.
|
||||
*/
|
||||
int32_t
|
||||
asn_get_few_bits(asn_bit_data_t *pd, int nbits) {
|
||||
size_t off; /* Next after last bit offset */
|
||||
ssize_t nleft; /* Number of bits left in this stream */
|
||||
uint32_t accum;
|
||||
const uint8_t *buf;
|
||||
|
||||
if(nbits < 0)
|
||||
return -1;
|
||||
|
||||
nleft = pd->nbits - pd->nboff;
|
||||
if(nbits > nleft) {
|
||||
int32_t tailv, vhead;
|
||||
if(!pd->refill || nbits > 31) return -1;
|
||||
/* Accumulate unused bytes before refill */
|
||||
ASN_DEBUG("Obtain the rest %d bits (want %d)",
|
||||
(int)nleft, (int)nbits);
|
||||
tailv = asn_get_few_bits(pd, nleft);
|
||||
if(tailv < 0) return -1;
|
||||
/* Refill (replace pd contents with new data) */
|
||||
if(pd->refill(pd))
|
||||
return -1;
|
||||
nbits -= nleft;
|
||||
vhead = asn_get_few_bits(pd, nbits);
|
||||
/* Combine the rest of previous pd with the head of new one */
|
||||
tailv = (tailv << nbits) | vhead; /* Could == -1 */
|
||||
return tailv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Normalize position indicator.
|
||||
*/
|
||||
if(pd->nboff >= 8) {
|
||||
pd->buffer += (pd->nboff >> 3);
|
||||
pd->nbits -= (pd->nboff & ~0x07);
|
||||
pd->nboff &= 0x07;
|
||||
}
|
||||
pd->moved += nbits;
|
||||
pd->nboff += nbits;
|
||||
off = pd->nboff;
|
||||
buf = pd->buffer;
|
||||
|
||||
/*
|
||||
* Extract specified number of bits.
|
||||
*/
|
||||
if(off <= 8)
|
||||
accum = nbits ? (buf[0]) >> (8 - off) : 0;
|
||||
else if(off <= 16)
|
||||
accum = ((buf[0] << 8) + buf[1]) >> (16 - off);
|
||||
else if(off <= 24)
|
||||
accum = ((buf[0] << 16) + (buf[1] << 8) + buf[2]) >> (24 - off);
|
||||
else if(off <= 31)
|
||||
accum = (((uint32_t)buf[0] << 24) + (buf[1] << 16)
|
||||
+ (buf[2] << 8) + (buf[3])) >> (32 - off);
|
||||
else if(nbits <= 31) {
|
||||
asn_bit_data_t tpd = *pd;
|
||||
/* Here are we with our 31-bits limit plus 1..7 bits offset. */
|
||||
asn_get_undo(&tpd, nbits);
|
||||
/* The number of available bits in the stream allow
|
||||
* for the following operations to take place without
|
||||
* invoking the ->refill() function */
|
||||
accum = asn_get_few_bits(&tpd, nbits - 24) << 24;
|
||||
accum |= asn_get_few_bits(&tpd, 24);
|
||||
} else {
|
||||
asn_get_undo(pd, nbits);
|
||||
return -1;
|
||||
}
|
||||
|
||||
accum &= (((uint32_t)1 << nbits) - 1);
|
||||
|
||||
ASN_DEBUG(" [PER got %2d<=%2d bits => span %d %+ld[%d..%d]:%02x (%d) => 0x%x]",
|
||||
(int)nbits, (int)nleft,
|
||||
(int)pd->moved,
|
||||
(((long)pd->buffer) & 0xf),
|
||||
(int)pd->nboff, (int)pd->nbits,
|
||||
((pd->buffer != NULL)?pd->buffer[0]:0),
|
||||
(int)(pd->nbits - pd->nboff),
|
||||
(int)accum);
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract a large number of bits from the specified PER data pointer.
|
||||
*/
|
||||
int
|
||||
asn_get_many_bits(asn_bit_data_t *pd, uint8_t *dst, int alright, int nbits) {
|
||||
int32_t value;
|
||||
|
||||
if(alright && (nbits & 7)) {
|
||||
/* Perform right alignment of a first few bits */
|
||||
value = asn_get_few_bits(pd, nbits & 0x07);
|
||||
if(value < 0) return -1;
|
||||
*dst++ = value; /* value is already right-aligned */
|
||||
nbits &= ~7;
|
||||
}
|
||||
|
||||
while(nbits) {
|
||||
if(nbits >= 24) {
|
||||
value = asn_get_few_bits(pd, 24);
|
||||
if(value < 0) return -1;
|
||||
*(dst++) = value >> 16;
|
||||
*(dst++) = value >> 8;
|
||||
*(dst++) = value;
|
||||
nbits -= 24;
|
||||
} else {
|
||||
value = asn_get_few_bits(pd, nbits);
|
||||
if(value < 0) return -1;
|
||||
if(nbits & 7) { /* implies left alignment */
|
||||
value <<= 8 - (nbits & 7),
|
||||
nbits += 8 - (nbits & 7);
|
||||
if(nbits > 24)
|
||||
*dst++ = value >> 24;
|
||||
}
|
||||
if(nbits > 16)
|
||||
*dst++ = value >> 16;
|
||||
if(nbits > 8)
|
||||
*dst++ = value >> 8;
|
||||
*dst++ = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put a small number of bits (<= 31).
|
||||
*/
|
||||
int
|
||||
asn_put_few_bits(asn_bit_outp_t *po, uint32_t bits, int obits) {
|
||||
size_t off; /* Next after last bit offset */
|
||||
size_t omsk; /* Existing last byte meaningful bits mask */
|
||||
uint8_t *buf;
|
||||
|
||||
if(obits <= 0 || obits >= 32) return obits ? -1 : 0;
|
||||
|
||||
ASN_DEBUG("[PER put %d bits %x to %p+%d bits]",
|
||||
obits, (int)bits, (void *)po->buffer, (int)po->nboff);
|
||||
|
||||
/*
|
||||
* Normalize position indicator.
|
||||
*/
|
||||
if(po->nboff >= 8) {
|
||||
po->buffer += (po->nboff >> 3);
|
||||
po->nbits -= (po->nboff & ~0x07);
|
||||
po->nboff &= 0x07;
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush whole-bytes output, if necessary.
|
||||
*/
|
||||
if(po->nboff + obits > po->nbits) {
|
||||
size_t complete_bytes;
|
||||
if(!po->buffer) po->buffer = po->tmpspace;
|
||||
complete_bytes = (po->buffer - po->tmpspace);
|
||||
ASN_DEBUG("[PER output %ld complete + %ld]",
|
||||
(long)complete_bytes, (long)po->flushed_bytes);
|
||||
if(po->output(po->tmpspace, complete_bytes, po->op_key) < 0)
|
||||
return -1;
|
||||
if(po->nboff)
|
||||
po->tmpspace[0] = po->buffer[0];
|
||||
po->buffer = po->tmpspace;
|
||||
po->nbits = 8 * sizeof(po->tmpspace);
|
||||
po->flushed_bytes += complete_bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, due to sizeof(tmpspace), we are guaranteed large enough space.
|
||||
*/
|
||||
buf = po->buffer;
|
||||
omsk = ~((1 << (8 - po->nboff)) - 1);
|
||||
off = (po->nboff + obits);
|
||||
|
||||
/* Clear data of debris before meaningful bits */
|
||||
bits &= (((uint32_t)1 << obits) - 1);
|
||||
|
||||
ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits,
|
||||
(int)bits, (int)bits,
|
||||
(int)po->nboff, (int)off,
|
||||
buf[0], (int)(omsk&0xff),
|
||||
(int)(buf[0] & omsk));
|
||||
|
||||
if(off <= 8) /* Completely within 1 byte */
|
||||
po->nboff = off,
|
||||
bits <<= (8 - off),
|
||||
buf[0] = (buf[0] & omsk) | bits;
|
||||
else if(off <= 16)
|
||||
po->nboff = off,
|
||||
bits <<= (16 - off),
|
||||
buf[0] = (buf[0] & omsk) | (bits >> 8),
|
||||
buf[1] = bits;
|
||||
else if(off <= 24)
|
||||
po->nboff = off,
|
||||
bits <<= (24 - off),
|
||||
buf[0] = (buf[0] & omsk) | (bits >> 16),
|
||||
buf[1] = bits >> 8,
|
||||
buf[2] = bits;
|
||||
else if(off <= 31)
|
||||
po->nboff = off,
|
||||
bits <<= (32 - off),
|
||||
buf[0] = (buf[0] & omsk) | (bits >> 24),
|
||||
buf[1] = bits >> 16,
|
||||
buf[2] = bits >> 8,
|
||||
buf[3] = bits;
|
||||
else {
|
||||
if(asn_put_few_bits(po, bits >> (obits - 24), 24)) return -1;
|
||||
if(asn_put_few_bits(po, bits, obits - 24)) return -1;
|
||||
}
|
||||
|
||||
ASN_DEBUG("[PER out %u/%x => %02x buf+%ld]",
|
||||
(int)bits, (int)bits, buf[0],
|
||||
(long)(po->buffer - po->tmpspace));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Output a large number of bits.
|
||||
*/
|
||||
int
|
||||
asn_put_many_bits(asn_bit_outp_t *po, const uint8_t *src, int nbits) {
|
||||
|
||||
while(nbits) {
|
||||
uint32_t value;
|
||||
|
||||
if(nbits >= 24) {
|
||||
value = (src[0] << 16) | (src[1] << 8) | src[2];
|
||||
src += 3;
|
||||
nbits -= 24;
|
||||
if(asn_put_few_bits(po, value, 24))
|
||||
return -1;
|
||||
} else {
|
||||
value = src[0];
|
||||
if(nbits > 8)
|
||||
value = (value << 8) | src[1];
|
||||
if(nbits > 16)
|
||||
value = (value << 8) | src[2];
|
||||
if(nbits & 0x07)
|
||||
value >>= (8 - (nbits & 0x07));
|
||||
if(asn_put_few_bits(po, value, nbits))
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
asn_put_aligned_flush(asn_bit_outp_t *po) {
|
||||
uint32_t unused_bits = (0x7 & (8 - (po->nboff & 0x07)));
|
||||
size_t complete_bytes =
|
||||
(po->buffer ? po->buffer - po->tmpspace : 0) + ((po->nboff + 7) >> 3);
|
||||
|
||||
if(unused_bits) {
|
||||
po->buffer[po->nboff >> 3] &= ~0u << unused_bits;
|
||||
}
|
||||
|
||||
if(po->output(po->tmpspace, complete_bytes, po->op_key) < 0) {
|
||||
return -1;
|
||||
} else {
|
||||
po->buffer = po->tmpspace;
|
||||
po->nboff = 0;
|
||||
po->nbits = 8 * sizeof(po->tmpspace);
|
||||
po->flushed_bytes += complete_bytes;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_BIT_DATA
|
||||
#define ASN_BIT_DATA
|
||||
|
||||
#include <asn_system.h> /* Platform-specific types */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This structure describes a position inside an incoming PER bit stream.
|
||||
*/
|
||||
typedef struct asn_bit_data_s {
|
||||
const uint8_t *buffer; /* Pointer to the octet stream */
|
||||
size_t nboff; /* Bit offset to the meaningful bit */
|
||||
size_t nbits; /* Number of bits in the stream */
|
||||
size_t moved; /* Number of bits moved through this bit stream */
|
||||
int (*refill)(struct asn_bit_data_s *);
|
||||
void *refill_key;
|
||||
} asn_bit_data_t;
|
||||
|
||||
/*
|
||||
* Create a contiguous non-refillable bit data structure.
|
||||
* Can be freed by FREEMEM().
|
||||
*/
|
||||
asn_bit_data_t *asn_bit_data_new_contiguous(const void *data, size_t size_bits);
|
||||
|
||||
/*
|
||||
* Extract a small number of bits (<= 31) from the specified PER data pointer.
|
||||
* This function returns -1 if the specified number of bits could not be
|
||||
* extracted due to EOD or other conditions.
|
||||
*/
|
||||
int32_t asn_get_few_bits(asn_bit_data_t *, int get_nbits);
|
||||
|
||||
/* Undo the immediately preceeding "get_few_bits" operation */
|
||||
void asn_get_undo(asn_bit_data_t *, int get_nbits);
|
||||
|
||||
/*
|
||||
* Extract a large number of bits from the specified PER data pointer.
|
||||
* This function returns -1 if the specified number of bits could not be
|
||||
* extracted due to EOD or other conditions.
|
||||
*/
|
||||
int asn_get_many_bits(asn_bit_data_t *, uint8_t *dst, int right_align,
|
||||
int get_nbits);
|
||||
|
||||
/* Non-thread-safe debugging function, don't use it */
|
||||
char *asn_bit_data_string(asn_bit_data_t *);
|
||||
|
||||
/*
|
||||
* This structure supports forming bit output.
|
||||
*/
|
||||
typedef struct asn_bit_outp_s {
|
||||
uint8_t *buffer; /* Pointer into the (tmpspace) */
|
||||
size_t nboff; /* Bit offset to the meaningful bit */
|
||||
size_t nbits; /* Number of bits left in (tmpspace) */
|
||||
uint8_t tmpspace[32]; /* Preliminary storage to hold data */
|
||||
int (*output)(const void *data, size_t size, void *op_key);
|
||||
void *op_key; /* Key for (output) data callback */
|
||||
size_t flushed_bytes; /* Bytes already flushed through (output) */
|
||||
} asn_bit_outp_t;
|
||||
|
||||
/* Output a small number of bits (<= 31) */
|
||||
int asn_put_few_bits(asn_bit_outp_t *, uint32_t bits, int obits);
|
||||
|
||||
/* Output a large number of bits */
|
||||
int asn_put_many_bits(asn_bit_outp_t *, const uint8_t *src, int put_nbits);
|
||||
|
||||
/*
|
||||
* Flush whole bytes (0 or more) through (outper) member.
|
||||
* The least significant bits which are not used are guaranteed to be set to 0.
|
||||
* Returns -1 if callback returns -1. Otherwise, 0.
|
||||
*/
|
||||
int asn_put_aligned_flush(asn_bit_outp_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ASN_BIT_DATA */
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_CODECS_H
|
||||
#define ASN_CODECS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct asn_TYPE_descriptor_s; /* Forward declaration */
|
||||
|
||||
/*
|
||||
* This structure defines a set of parameters that may be passed
|
||||
* to every ASN.1 encoder or decoder function.
|
||||
* WARNING: if max_stack_size member is set, and you are calling the
|
||||
* function pointers of the asn_TYPE_descriptor_t directly,
|
||||
* this structure must be ALLOCATED ON THE STACK!
|
||||
* If you can't always satisfy this requirement, use ber_decode(),
|
||||
* xer_decode() and uper_decode() functions instead.
|
||||
*/
|
||||
typedef struct asn_codec_ctx_s {
|
||||
/*
|
||||
* Limit the decoder routines to use no (much) more stack than a given
|
||||
* number of bytes. Most of decoders are stack-based, and this
|
||||
* would protect against stack overflows if the number of nested
|
||||
* encodings is high.
|
||||
* The OCTET STRING, BIT STRING and ANY BER decoders are heap-based,
|
||||
* and are safe from this kind of overflow.
|
||||
* A value from getrlimit(RLIMIT_STACK) may be used to initialize
|
||||
* this variable. Be careful in multithreaded environments, as the
|
||||
* stack size is rather limited.
|
||||
*/
|
||||
size_t max_stack_size; /* 0 disables stack bounds checking */
|
||||
} asn_codec_ctx_t;
|
||||
|
||||
/*
|
||||
* Type of the return value of the encoding functions (der_encode, xer_encode).
|
||||
*/
|
||||
typedef struct asn_enc_rval_s {
|
||||
/*
|
||||
* Number of bytes encoded.
|
||||
* -1 indicates failure to encode the structure.
|
||||
* In this case, the members below this one are meaningful.
|
||||
*/
|
||||
ssize_t encoded;
|
||||
|
||||
/*
|
||||
* Members meaningful when (encoded == -1), for post mortem analysis.
|
||||
*/
|
||||
|
||||
/* Type which cannot be encoded */
|
||||
const struct asn_TYPE_descriptor_s *failed_type;
|
||||
|
||||
/* Pointer to the structure of that type */
|
||||
const void *structure_ptr;
|
||||
} asn_enc_rval_t;
|
||||
#define ASN__ENCODE_FAILED do { \
|
||||
asn_enc_rval_t tmp_error; \
|
||||
tmp_error.encoded = -1; \
|
||||
tmp_error.failed_type = td; \
|
||||
tmp_error.structure_ptr = sptr; \
|
||||
ASN_DEBUG("Failed to encode element %s", td ? td->name : ""); \
|
||||
return tmp_error; \
|
||||
} while(0)
|
||||
#define ASN__ENCODED_OK(rval) do { \
|
||||
rval.structure_ptr = 0; \
|
||||
rval.failed_type = 0; \
|
||||
return rval; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Type of the return value of the decoding functions (ber_decode, xer_decode)
|
||||
*
|
||||
* Please note that the number of consumed bytes is ALWAYS meaningful,
|
||||
* even if code==RC_FAIL. This is to indicate the number of successfully
|
||||
* decoded bytes, hence providing a possibility to fail with more diagnostics
|
||||
* (i.e., print the offending remainder of the buffer).
|
||||
*/
|
||||
enum asn_dec_rval_code_e {
|
||||
RC_OK, /* Decoded successfully */
|
||||
RC_WMORE, /* More data expected, call again */
|
||||
RC_FAIL /* Failure to decode data */
|
||||
};
|
||||
typedef struct asn_dec_rval_s {
|
||||
enum asn_dec_rval_code_e code; /* Result code */
|
||||
size_t consumed; /* Number of bytes consumed */
|
||||
} asn_dec_rval_t;
|
||||
#define ASN__DECODE_FAILED do { \
|
||||
asn_dec_rval_t tmp_error; \
|
||||
tmp_error.code = RC_FAIL; \
|
||||
tmp_error.consumed = 0; \
|
||||
ASN_DEBUG("Failed to decode element %s", td ? td->name : ""); \
|
||||
return tmp_error; \
|
||||
} while(0)
|
||||
#define ASN__DECODE_STARVED do { \
|
||||
asn_dec_rval_t tmp_error; \
|
||||
tmp_error.code = RC_WMORE; \
|
||||
tmp_error.consumed = 0; \
|
||||
return tmp_error; \
|
||||
} while(0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ASN_CODECS_H */
|
||||
@@ -0,0 +1,317 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <asn_codecs_prim.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* Decode an always-primitive type.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
ber_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
const void *buf_ptr, size_t size, int tag_mode) {
|
||||
ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
|
||||
asn_dec_rval_t rval;
|
||||
ber_tlv_len_t length = 0; /* =0 to avoid [incorrect] warning. */
|
||||
|
||||
/*
|
||||
* If the structure is not there, allocate it.
|
||||
*/
|
||||
if(st == NULL) {
|
||||
st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
|
||||
if(st == NULL) ASN__DECODE_FAILED;
|
||||
*sptr = (void *)st;
|
||||
}
|
||||
|
||||
ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
|
||||
td->name, tag_mode);
|
||||
|
||||
/*
|
||||
* Check tags and extract value length.
|
||||
*/
|
||||
rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
|
||||
tag_mode, 0, &length, 0);
|
||||
if(rval.code != RC_OK)
|
||||
return rval;
|
||||
|
||||
ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
|
||||
|
||||
/*
|
||||
* Make sure we have this length.
|
||||
*/
|
||||
buf_ptr = ((const char *)buf_ptr) + rval.consumed;
|
||||
size -= rval.consumed;
|
||||
if(length > (ber_tlv_len_t)size) {
|
||||
rval.code = RC_WMORE;
|
||||
rval.consumed = 0;
|
||||
return rval;
|
||||
}
|
||||
|
||||
st->size = (int)length;
|
||||
/* The following better be optimized away. */
|
||||
if(sizeof(st->size) != sizeof(length)
|
||||
&& (ber_tlv_len_t)st->size != length) {
|
||||
st->size = 0;
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
st->buf = (uint8_t *)MALLOC(length + 1);
|
||||
if(!st->buf) {
|
||||
st->size = 0;
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memcpy(st->buf, buf_ptr, length);
|
||||
st->buf[length] = '\0'; /* Just in case */
|
||||
|
||||
rval.code = RC_OK;
|
||||
rval.consumed += length;
|
||||
|
||||
ASN_DEBUG("Took %ld/%ld bytes to encode %s",
|
||||
(long)rval.consumed,
|
||||
(long)length, td->name);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode an always-primitive type using DER.
|
||||
*/
|
||||
asn_enc_rval_t
|
||||
der_encode_primitive(const asn_TYPE_descriptor_t *td, const void *sptr,
|
||||
int tag_mode, ber_tlv_tag_t tag,
|
||||
asn_app_consume_bytes_f *cb, void *app_key) {
|
||||
asn_enc_rval_t erval;
|
||||
const ASN__PRIMITIVE_TYPE_t *st = (const ASN__PRIMITIVE_TYPE_t *)sptr;
|
||||
|
||||
ASN_DEBUG("%s %s as a primitive type (tm=%d)",
|
||||
cb?"Encoding":"Estimating", td->name, tag_mode);
|
||||
|
||||
erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
|
||||
cb, app_key);
|
||||
ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
|
||||
if(erval.encoded == -1) {
|
||||
erval.failed_type = td;
|
||||
erval.structure_ptr = sptr;
|
||||
return erval;
|
||||
}
|
||||
|
||||
if(cb && st->buf) {
|
||||
if(cb(st->buf, st->size, app_key) < 0) {
|
||||
erval.encoded = -1;
|
||||
erval.failed_type = td;
|
||||
erval.structure_ptr = sptr;
|
||||
return erval;
|
||||
}
|
||||
} else {
|
||||
assert(st->buf || st->size == 0);
|
||||
}
|
||||
|
||||
erval.encoded += st->size;
|
||||
ASN__ENCODED_OK(erval);
|
||||
}
|
||||
|
||||
void
|
||||
ASN__PRIMITIVE_TYPE_free(const asn_TYPE_descriptor_t *td, void *sptr,
|
||||
enum asn_struct_free_method method) {
|
||||
ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
|
||||
|
||||
if(!td || !sptr)
|
||||
return;
|
||||
|
||||
ASN_DEBUG("Freeing %s as a primitive type", td->name);
|
||||
|
||||
if(st->buf)
|
||||
FREEMEM(st->buf);
|
||||
|
||||
switch(method) {
|
||||
case ASFM_FREE_EVERYTHING:
|
||||
FREEMEM(sptr);
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING:
|
||||
break;
|
||||
case ASFM_FREE_UNDERLYING_AND_RESET:
|
||||
memset(sptr, 0, sizeof(ASN__PRIMITIVE_TYPE_t));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local internal type passed around as an argument.
|
||||
*/
|
||||
struct xdp_arg_s {
|
||||
const asn_TYPE_descriptor_t *type_descriptor;
|
||||
void *struct_key;
|
||||
xer_primitive_body_decoder_f *prim_body_decoder;
|
||||
int decoded_something;
|
||||
int want_more;
|
||||
};
|
||||
|
||||
/*
|
||||
* Since some kinds of primitive values can be encoded using value-specific
|
||||
* tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive decoder must
|
||||
* be supplied with such tags to parse them as needed.
|
||||
*/
|
||||
static int
|
||||
xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
|
||||
struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
|
||||
enum xer_pbd_rval bret;
|
||||
|
||||
/*
|
||||
* The chunk_buf is guaranteed to start at '<'.
|
||||
*/
|
||||
assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
|
||||
|
||||
/*
|
||||
* Decoding was performed once already. Prohibit doing it again.
|
||||
*/
|
||||
if(arg->decoded_something)
|
||||
return -1;
|
||||
|
||||
bret = arg->prim_body_decoder(arg->type_descriptor,
|
||||
arg->struct_key, chunk_buf, chunk_size);
|
||||
switch(bret) {
|
||||
case XPBD_SYSTEM_FAILURE:
|
||||
case XPBD_DECODER_LIMIT:
|
||||
case XPBD_BROKEN_ENCODING:
|
||||
break;
|
||||
case XPBD_BODY_CONSUMED:
|
||||
/* Tag decoded successfully */
|
||||
arg->decoded_something = 1;
|
||||
/* Fall through */
|
||||
case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
|
||||
struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
|
||||
enum xer_pbd_rval bret;
|
||||
size_t lead_wsp_size;
|
||||
|
||||
if(arg->decoded_something) {
|
||||
if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
|
||||
/*
|
||||
* Example:
|
||||
* "<INTEGER>123<!--/--> </INTEGER>"
|
||||
* ^- chunk_buf position.
|
||||
*/
|
||||
return chunk_size;
|
||||
}
|
||||
/*
|
||||
* Decoding was done once already. Prohibit doing it again.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!have_more) {
|
||||
/*
|
||||
* If we've received something like "1", we can't really
|
||||
* tell whether it is really `1` or `123`, until we know
|
||||
* that there is no more data coming.
|
||||
* The have_more argument will be set to 1 once something
|
||||
* like this is available to the caller of this callback:
|
||||
* "1<tag_start..."
|
||||
*/
|
||||
arg->want_more = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size);
|
||||
chunk_buf = (const char *)chunk_buf + lead_wsp_size;
|
||||
chunk_size -= lead_wsp_size;
|
||||
|
||||
bret = arg->prim_body_decoder(arg->type_descriptor,
|
||||
arg->struct_key, chunk_buf, chunk_size);
|
||||
switch(bret) {
|
||||
case XPBD_SYSTEM_FAILURE:
|
||||
case XPBD_DECODER_LIMIT:
|
||||
case XPBD_BROKEN_ENCODING:
|
||||
break;
|
||||
case XPBD_BODY_CONSUMED:
|
||||
/* Tag decoded successfully */
|
||||
arg->decoded_something = 1;
|
||||
/* Fall through */
|
||||
case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
|
||||
return lead_wsp_size + chunk_size;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
asn_dec_rval_t
|
||||
xer_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, void **sptr,
|
||||
size_t struct_size, const char *opt_mname,
|
||||
const void *buf_ptr, size_t size,
|
||||
xer_primitive_body_decoder_f *prim_body_decoder) {
|
||||
const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
|
||||
asn_struct_ctx_t s_ctx;
|
||||
struct xdp_arg_s s_arg;
|
||||
asn_dec_rval_t rc;
|
||||
|
||||
/*
|
||||
* Create the structure if does not exist.
|
||||
*/
|
||||
if(!*sptr) {
|
||||
*sptr = CALLOC(1, struct_size);
|
||||
if(!*sptr) ASN__DECODE_FAILED;
|
||||
}
|
||||
|
||||
memset(&s_ctx, 0, sizeof(s_ctx));
|
||||
s_arg.type_descriptor = td;
|
||||
s_arg.struct_key = *sptr;
|
||||
s_arg.prim_body_decoder = prim_body_decoder;
|
||||
s_arg.decoded_something = 0;
|
||||
s_arg.want_more = 0;
|
||||
|
||||
rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
|
||||
xml_tag, buf_ptr, size,
|
||||
xer_decode__unexpected_tag, xer_decode__primitive_body);
|
||||
switch(rc.code) {
|
||||
case RC_OK:
|
||||
if(!s_arg.decoded_something) {
|
||||
char ch;
|
||||
ASN_DEBUG("Primitive body is not recognized, "
|
||||
"supplying empty one");
|
||||
/*
|
||||
* Decoding opportunity has come and gone.
|
||||
* Where's the result?
|
||||
* Try to feed with empty body, see if it eats it.
|
||||
*/
|
||||
if(prim_body_decoder(s_arg.type_descriptor,
|
||||
s_arg.struct_key, &ch, 0)
|
||||
!= XPBD_BODY_CONSUMED) {
|
||||
/*
|
||||
* This decoder does not like empty stuff.
|
||||
*/
|
||||
ASN__DECODE_FAILED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RC_WMORE:
|
||||
/*
|
||||
* Redo the whole thing later.
|
||||
* We don't have a context to save intermediate parsing state.
|
||||
*/
|
||||
rc.consumed = 0;
|
||||
break;
|
||||
case RC_FAIL:
|
||||
rc.consumed = 0;
|
||||
if(s_arg.want_more)
|
||||
rc.code = RC_WMORE;
|
||||
else
|
||||
ASN__DECODE_FAILED;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*-
|
||||
* Copyright (c) 2004-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_CODECS_PRIM_H
|
||||
#define ASN_CODECS_PRIM_H
|
||||
|
||||
#include <asn_application.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct ASN__PRIMITIVE_TYPE_s {
|
||||
uint8_t *buf; /* Buffer with consecutive primitive encoding bytes */
|
||||
size_t size; /* Size of the buffer */
|
||||
} ASN__PRIMITIVE_TYPE_t; /* Do not use this type directly! */
|
||||
|
||||
asn_struct_free_f ASN__PRIMITIVE_TYPE_free;
|
||||
ber_type_decoder_f ber_decode_primitive;
|
||||
der_type_encoder_f der_encode_primitive;
|
||||
|
||||
/*
|
||||
* A callback specification for the xer_decode_primitive() function below.
|
||||
*/
|
||||
enum xer_pbd_rval {
|
||||
XPBD_SYSTEM_FAILURE, /* System failure (memory shortage, etc) */
|
||||
XPBD_DECODER_LIMIT, /* Hit some decoder limitation or deficiency */
|
||||
XPBD_BROKEN_ENCODING, /* Encoding of a primitive body is broken */
|
||||
XPBD_NOT_BODY_IGNORE, /* Not a body format, but safe to ignore */
|
||||
XPBD_BODY_CONSUMED /* Body is recognized and consumed */
|
||||
};
|
||||
typedef enum xer_pbd_rval(xer_primitive_body_decoder_f)(
|
||||
const asn_TYPE_descriptor_t *td, void *struct_ptr, const void *chunk_buf,
|
||||
size_t chunk_size);
|
||||
|
||||
/*
|
||||
* Specific function to decode simple primitive types.
|
||||
* Also see xer_decode_general() in xer_decoder.h
|
||||
*/
|
||||
asn_dec_rval_t xer_decode_primitive(
|
||||
const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *type_descriptor, void **struct_ptr,
|
||||
size_t struct_size, const char *opt_mname, const void *buf_ptr, size_t size,
|
||||
xer_primitive_body_decoder_f *prim_body_decoder);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ASN_CODECS_PRIM_H */
|
||||
@@ -0,0 +1,47 @@
|
||||
#include <asn_internal.h>
|
||||
|
||||
ssize_t
|
||||
asn__format_to_callback(int (*cb)(const void *, size_t, void *key), void *key,
|
||||
const char *fmt, ...) {
|
||||
char scratch[64];
|
||||
char *buf = scratch;
|
||||
size_t buf_size = sizeof(scratch);
|
||||
int wrote;
|
||||
int cb_ret;
|
||||
|
||||
do {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
wrote = vsnprintf(buf, buf_size, fmt, args);
|
||||
if(wrote < (ssize_t)buf_size) {
|
||||
if(wrote < 0) {
|
||||
if(buf != scratch) FREEMEM(buf);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
buf_size <<= 1;
|
||||
if(buf == scratch) {
|
||||
buf = MALLOC(buf_size);
|
||||
if(!buf) return -1;
|
||||
} else {
|
||||
void *p = REALLOC(buf, buf_size);
|
||||
if(!p) {
|
||||
FREEMEM(buf);
|
||||
return -1;
|
||||
}
|
||||
buf = p;
|
||||
}
|
||||
} while(1);
|
||||
|
||||
cb_ret = cb(buf, wrote, key);
|
||||
if(buf != scratch) FREEMEM(buf);
|
||||
if(cb_ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return wrote;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* Declarations internally useful for the ASN.1 support code.
|
||||
*/
|
||||
#ifndef ASN_INTERNAL_H
|
||||
#define ASN_INTERNAL_H
|
||||
#ifndef __EXTENSIONS__
|
||||
#define __EXTENSIONS__ /* for Sun */
|
||||
#endif
|
||||
#include "asn_application.h" /* Application-visible API */
|
||||
|
||||
#ifndef __NO_ASSERT_H__ /* Include assert.h only for internal use. */
|
||||
#include <assert.h> /* for assert() macro */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Environment version might be used to avoid running with the old library */
|
||||
#define ASN1C_ENVIRONMENT_VERSION 923 /* Compile-time version */
|
||||
int get_asn1c_environment_version(void); /* Run-time version */
|
||||
|
||||
#define CALLOC(nmemb, size) calloc(nmemb, size)
|
||||
#define MALLOC(size) malloc(size)
|
||||
#define REALLOC(oldptr, size) realloc(oldptr, size)
|
||||
#define FREEMEM(ptr) free(ptr)
|
||||
|
||||
#define asn_debug_indent 0
|
||||
#define ASN_DEBUG_INDENT_ADD(i) do{}while(0)
|
||||
|
||||
#ifdef EMIT_ASN_DEBUG
|
||||
#warning "Use ASN_EMIT_DEBUG instead of EMIT_ASN_DEBUG"
|
||||
#define ASN_EMIT_DEBUG EMIT_ASN_DEBUG
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A macro for debugging the ASN.1 internals.
|
||||
* You may enable or override it.
|
||||
*/
|
||||
#ifndef ASN_DEBUG /* If debugging code is not defined elsewhere... */
|
||||
#if ASN_EMIT_DEBUG == 1 /* And it was asked to emit this code... */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#ifdef ASN_THREAD_SAFE
|
||||
/* Thread safety requires sacrifice in output indentation:
|
||||
* Retain empty definition of ASN_DEBUG_INDENT_ADD. */
|
||||
#else /* !ASN_THREAD_SAFE */
|
||||
#undef ASN_DEBUG_INDENT_ADD
|
||||
#undef asn_debug_indent
|
||||
int asn_debug_indent;
|
||||
#define ASN_DEBUG_INDENT_ADD(i) do { asn_debug_indent += i; } while(0)
|
||||
#endif /* ASN_THREAD_SAFE */
|
||||
#define ASN_DEBUG(fmt, args...) do { \
|
||||
int adi = asn_debug_indent; \
|
||||
while(adi--) fprintf(stderr, " "); \
|
||||
fprintf(stderr, fmt, ##args); \
|
||||
fprintf(stderr, " (%s:%d)\n", \
|
||||
__FILE__, __LINE__); \
|
||||
} while(0)
|
||||
#else /* !C99 */
|
||||
void CC_PRINTFLIKE(1, 2) ASN_DEBUG_f(const char *fmt, ...);
|
||||
#define ASN_DEBUG ASN_DEBUG_f
|
||||
#endif /* C99 */
|
||||
#else /* ASN_EMIT_DEBUG != 1 */
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define ASN_DEBUG(...) do{}while(0)
|
||||
#else /* not C99 */
|
||||
static void CC_PRINTFLIKE(1, 2) ASN_DEBUG(const char *fmt, ...) { (void)fmt; }
|
||||
#endif /* C99 or better */
|
||||
#endif /* ASN_EMIT_DEBUG */
|
||||
#endif /* ASN_DEBUG */
|
||||
|
||||
/*
|
||||
* Print to a callback.
|
||||
* The callback is expected to return negative values on error.
|
||||
* 0 and positive values are treated as success.
|
||||
* RETURN VALUES:
|
||||
* -1: Failed to format or invoke the callback.
|
||||
* >0: Size of the data that got delivered to the callback.
|
||||
*/
|
||||
ssize_t CC_PRINTFLIKE(3, 4)
|
||||
asn__format_to_callback(
|
||||
int (*callback)(const void *, size_t, void *key), void *key,
|
||||
const char *fmt, ...);
|
||||
|
||||
/*
|
||||
* Invoke the application-supplied callback and fail, if something is wrong.
|
||||
*/
|
||||
#define ASN__E_cbc(buf, size) (cb((buf), (size), app_key) < 0)
|
||||
#define ASN__E_CALLBACK(size, foo) \
|
||||
do { \
|
||||
if(foo) goto cb_failed; \
|
||||
er.encoded += (size); \
|
||||
} while(0)
|
||||
#define ASN__CALLBACK(buf, size) ASN__E_CALLBACK(size, ASN__E_cbc(buf, size))
|
||||
#define ASN__CALLBACK2(buf1, size1, buf2, size2) \
|
||||
ASN__E_CALLBACK((size1) + (size2), \
|
||||
ASN__E_cbc(buf1, size1) || ASN__E_cbc(buf2, size2))
|
||||
#define ASN__CALLBACK3(buf1, size1, buf2, size2, buf3, size3) \
|
||||
ASN__E_CALLBACK((size1) + (size2) + (size3), \
|
||||
ASN__E_cbc(buf1, size1) || ASN__E_cbc(buf2, size2) \
|
||||
|| ASN__E_cbc(buf3, size3))
|
||||
|
||||
#define ASN__TEXT_INDENT(nl, level) \
|
||||
do { \
|
||||
int tmp_level = (level); \
|
||||
int tmp_nl = ((nl) != 0); \
|
||||
int tmp_i; \
|
||||
if(tmp_nl) ASN__CALLBACK("\n", 1); \
|
||||
if(tmp_level < 0) tmp_level = 0; \
|
||||
for(tmp_i = 0; tmp_i < tmp_level; tmp_i++) ASN__CALLBACK(" ", 4); \
|
||||
} while(0)
|
||||
|
||||
#define _i_INDENT(nl) do { \
|
||||
int tmp_i; \
|
||||
if((nl) && cb("\n", 1, app_key) < 0) \
|
||||
return -1; \
|
||||
for(tmp_i = 0; tmp_i < ilevel; tmp_i++) \
|
||||
if(cb(" ", 4, app_key) < 0) \
|
||||
return -1; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Check stack against overflow, if limit is set.
|
||||
*/
|
||||
#define ASN__DEFAULT_STACK_MAX (30000)
|
||||
static int CC_NOTUSED
|
||||
ASN__STACK_OVERFLOW_CHECK(const asn_codec_ctx_t *ctx) {
|
||||
if(ctx && ctx->max_stack_size) {
|
||||
|
||||
/* ctx MUST be allocated on the stack */
|
||||
ptrdiff_t usedstack = ((const char *)ctx - (const char *)&ctx);
|
||||
if(usedstack > 0) usedstack = -usedstack; /* grows up! */
|
||||
|
||||
/* double negative required to avoid int wrap-around */
|
||||
if(usedstack < -(ptrdiff_t)ctx->max_stack_size) {
|
||||
ASN_DEBUG("Stack limit %ld reached",
|
||||
(long)ctx->max_stack_size);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ASN_INTERNAL_H */
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Run-time support for Information Object Classes.
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_IOC_H
|
||||
#define ASN_IOC_H
|
||||
|
||||
#include <asn_system.h> /* Platform-specific types */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct asn_TYPE_descriptor_s;
|
||||
struct asn_ioc_cell_s;
|
||||
|
||||
/*
|
||||
* X.681, #13
|
||||
*/
|
||||
typedef struct asn_ioc_set_s {
|
||||
size_t rows_count;
|
||||
size_t columns_count;
|
||||
const struct asn_ioc_cell_s *rows;
|
||||
} asn_ioc_set_t;
|
||||
|
||||
|
||||
typedef struct asn_ioc_cell_s {
|
||||
const char *field_name; /* Is equal to corresponding column_name */
|
||||
enum {
|
||||
aioc__value,
|
||||
aioc__type,
|
||||
aioc__open_type,
|
||||
} cell_kind;
|
||||
struct asn_TYPE_descriptor_s *type_descriptor;
|
||||
const void *value_sptr;
|
||||
struct {
|
||||
size_t types_count;
|
||||
struct {
|
||||
unsigned choice_position;
|
||||
} *types;
|
||||
} open_type;
|
||||
} asn_ioc_cell_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ASN_IOC_H */
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
|
||||
* All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
#include <asn_random_fill.h>
|
||||
#include <constr_TYPE.h>
|
||||
|
||||
int
|
||||
asn_random_fill(const struct asn_TYPE_descriptor_s *td, void **struct_ptr,
|
||||
size_t length) {
|
||||
|
||||
if(td && td->op->random_fill) {
|
||||
asn_random_fill_result_t res =
|
||||
td->op->random_fill(td, struct_ptr, 0, length);
|
||||
return (res.code == ARFILL_OK) ? 0 : -1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static uintmax_t
|
||||
asn__intmax_range(intmax_t lb, intmax_t ub) {
|
||||
assert(lb <= ub);
|
||||
if((ub < 0) == (lb < 0)) {
|
||||
return ub - lb;
|
||||
} else if(lb < 0) {
|
||||
return 1 + ((uintmax_t)ub + (uintmax_t)-(lb + 1));
|
||||
} else {
|
||||
assert(!"Unreachable");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
intmax_t
|
||||
asn_random_between(intmax_t lb, intmax_t rb) {
|
||||
if(lb == rb) {
|
||||
return lb;
|
||||
} else {
|
||||
const uintmax_t intmax_max = ((~(uintmax_t)0) >> 1);
|
||||
uintmax_t range = asn__intmax_range(lb, rb);
|
||||
uintmax_t value = 0;
|
||||
uintmax_t got_entropy = 0;
|
||||
|
||||
assert(RAND_MAX > 0xffffff); /* Seen 7ffffffd! */
|
||||
assert(range < intmax_max);
|
||||
|
||||
for(; got_entropy < range;) {
|
||||
got_entropy = (got_entropy << 24) | 0xffffff;
|
||||
value = (value << 24) | (random() % 0xffffff);
|
||||
}
|
||||
|
||||
return lb + (intmax_t)(value % (range + 1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#ifndef ASN_RANDOM_FILL
|
||||
#define ASN_RANDOM_FILL
|
||||
|
||||
/* Forward declarations */
|
||||
struct asn_TYPE_descriptor_s;
|
||||
struct asn_encoding_constraints_s;
|
||||
|
||||
/*
|
||||
* Initialize a structure with random data according to the type specification
|
||||
* and optional member constraints.
|
||||
* ARGUMENTS:
|
||||
* (max_length) - See (approx_max_length_limit).
|
||||
* (memb_constraints) - Member constraints, if exist.
|
||||
* The type can be constrained differently according
|
||||
* to PER and OER specifications, so we find a value
|
||||
* at the intersection of these constraints.
|
||||
* In case the return differs from ARFILL_OK, the (struct_ptr) contents
|
||||
* and (current_length) value remain in their original state.
|
||||
*/
|
||||
typedef struct asn_random_fill_result_s {
|
||||
enum {
|
||||
ARFILL_FAILED = -1, /* System error (memory?) */
|
||||
ARFILL_OK = 0, /* Initialization succeeded */
|
||||
ARFILL_SKIPPED = 1 /* Not done due to (length?) constraint */
|
||||
} code;
|
||||
size_t length; /* Approximate number of bytes created. */
|
||||
} asn_random_fill_result_t;
|
||||
typedef asn_random_fill_result_t(asn_random_fill_f)(
|
||||
const struct asn_TYPE_descriptor_s *td, void **struct_ptr,
|
||||
const struct asn_encoding_constraints_s *memb_constraints,
|
||||
size_t max_length);
|
||||
|
||||
/*
|
||||
* Returns 0 if the structure was properly initialized, -1 otherwise.
|
||||
* The (approx_max_length_limit) specifies the approximate limit of the
|
||||
* resulting structure in units closely resembling bytes. The actual result
|
||||
* might be several times larger or smaller than the length limit.
|
||||
*/
|
||||
int asn_random_fill(const struct asn_TYPE_descriptor_s *td, void **struct_ptr,
|
||||
size_t approx_max_length_limit);
|
||||
|
||||
/*
|
||||
* Returns a random number between min and max.
|
||||
*/
|
||||
intmax_t asn_random_between(intmax_t min, intmax_t max);
|
||||
|
||||
#endif /* ASN_RANDOM_FILL */
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
/*
|
||||
* Miscellaneous system-dependent types.
|
||||
*/
|
||||
#ifndef ASN_SYSTEM_H
|
||||
#define ASN_SYSTEM_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE 1
|
||||
#endif
|
||||
|
||||
#ifndef _BSD_SOURCE
|
||||
#define _BSD_SOURCE /* for snprintf() on some linux systems */
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* For snprintf(3) */
|
||||
#include <stdlib.h> /* For *alloc(3) */
|
||||
#include <string.h> /* For memcpy(3) */
|
||||
#include <sys/types.h> /* For size_t */
|
||||
#include <limits.h> /* For LONG_MAX */
|
||||
#include <stdarg.h> /* For va_start */
|
||||
#include <stddef.h> /* for offsetof and ptrdiff_t */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <malloc.h>
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
|
||||
/* To avoid linking with ws2_32.lib, here's the definition of ntohl() */
|
||||
#define sys_ntohl(l) ((((l) << 24) & 0xff000000) \
|
||||
| (((l) << 8) & 0xff0000) \
|
||||
| (((l) >> 8) & 0xff00) \
|
||||
| ((l >> 24) & 0xff))
|
||||
|
||||
#ifdef _MSC_VER /* MSVS.Net */
|
||||
#ifndef __cplusplus
|
||||
#define inline __inline
|
||||
#endif
|
||||
#ifndef ASSUMESTDTYPES /* Standard types have been defined elsewhere */
|
||||
#define ssize_t SSIZE_T
|
||||
#if _MSC_VER < 1600
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else /* _MSC_VER >= 1600 */
|
||||
#include <stdint.h>
|
||||
#endif /* _MSC_VER < 1600 */
|
||||
#endif /* ASSUMESTDTYPES */
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <float.h>
|
||||
#define isnan _isnan
|
||||
#define finite _finite
|
||||
#define copysign _copysign
|
||||
#define ilogb _logb
|
||||
#else /* !_MSC_VER */
|
||||
#include <stdint.h>
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#else /* !_WIN32 */
|
||||
|
||||
#if defined(__vxworks)
|
||||
#include <types/vxTypes.h>
|
||||
#else /* !defined(__vxworks) */
|
||||
|
||||
#include <inttypes.h> /* C99 specifies this file */
|
||||
#include <netinet/in.h> /* for ntohl() */
|
||||
#define sys_ntohl(foo) ntohl(foo)
|
||||
#endif /* defined(__vxworks) */
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#if __GNUC__ >= 3 || defined(__clang__)
|
||||
#define CC_ATTRIBUTE(attr) __attribute__((attr))
|
||||
#else
|
||||
#define CC_ATTRIBUTE(attr)
|
||||
#endif
|
||||
#define CC_PRINTFLIKE(fmt, var) CC_ATTRIBUTE(format(printf, fmt, var))
|
||||
#define CC_NOTUSED CC_ATTRIBUTE(unused)
|
||||
#ifndef CC_ATTR_NO_SANITIZE
|
||||
#define CC_ATTR_NO_SANITIZE(what) CC_ATTRIBUTE(no_sanitize(what))
|
||||
#endif
|
||||
|
||||
/* Figure out if thread safety is requested */
|
||||
#if !defined(ASN_THREAD_SAFE) && (defined(THREAD_SAFE) || defined(_REENTRANT))
|
||||
#define ASN_THREAD_SAFE
|
||||
#endif /* Thread safety */
|
||||
|
||||
#ifndef offsetof /* If not defined by <stddef.h> */
|
||||
#define offsetof(s, m) ((ptrdiff_t)&(((s *)0)->m) - (ptrdiff_t)((s *)0))
|
||||
#endif /* offsetof */
|
||||
|
||||
#ifndef MIN /* Suitable for comparing primitive types (integers) */
|
||||
#if defined(__GNUC__)
|
||||
#define MIN(a,b) ({ __typeof a _a = a; __typeof b _b = b; \
|
||||
((_a)<(_b)?(_a):(_b)); })
|
||||
#else /* !__GNUC__ */
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b)) /* Unsafe variant */
|
||||
#endif /* __GNUC__ */
|
||||
#endif /* MIN */
|
||||
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#ifndef SIZE_MAX
|
||||
#define SIZE_MAX ((~((size_t)0)) >> 1)
|
||||
#endif
|
||||
|
||||
#ifndef RSIZE_MAX /* C11, Annex K */
|
||||
#define RSIZE_MAX (SIZE_MAX >> 1)
|
||||
#endif
|
||||
#ifndef RSSIZE_MAX /* Halve signed size even further than unsigned */
|
||||
#define RSSIZE_MAX ((ssize_t)(RSIZE_MAX >> 1))
|
||||
#endif
|
||||
#else /* Old compiler */
|
||||
#undef SIZE_MAX
|
||||
#undef RSIZE_MAX
|
||||
#undef RSSIZE_MAX
|
||||
#define SIZE_MAX ((~((size_t)0)) >> 1)
|
||||
#define RSIZE_MAX (SIZE_MAX >> 1)
|
||||
#define RSSIZE_MAX ((ssize_t)(RSIZE_MAX >> 1))
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define ASN_PRI_SIZE "zu"
|
||||
#define ASN_PRI_SSIZE "zd"
|
||||
#define ASN_PRIuMAX PRIuMAX
|
||||
#define ASN_PRIdMAX PRIdMAX
|
||||
#else
|
||||
#define ASN_PRI_SIZE "lu"
|
||||
#define ASN_PRI_SSIZE "ld"
|
||||
#if LLONG_MAX > LONG_MAX
|
||||
#define ASN_PRIuMAX "llu"
|
||||
#define ASN_PRIdMAX "lld"
|
||||
#else
|
||||
#define ASN_PRIuMAX "lu"
|
||||
#define ASN_PRIdMAX "ld"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* ASN_SYSTEM_H */
|
||||
@@ -0,0 +1,283 @@
|
||||
/*-
|
||||
* Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
|
||||
* Redistribution and modifications are permitted subject to BSD license.
|
||||
*/
|
||||
#include <asn_internal.h>
|
||||
|
||||
#undef ADVANCE
|
||||
#define ADVANCE(num_bytes) do { \
|
||||
size_t num = num_bytes; \
|
||||
ptr = ((const char *)ptr) + num; \
|
||||
size -= num; \
|
||||
consumed_myself += num; \
|
||||
} while(0)
|
||||
#undef RETURN
|
||||
#define RETURN(_code) do { \
|
||||
asn_dec_rval_t rval; \
|
||||
rval.code = _code; \
|
||||
if(opt_ctx) opt_ctx->step = step; /* Save context */ \
|
||||
if(_code == RC_OK || opt_ctx) \
|
||||
rval.consumed = consumed_myself; \
|
||||
else \
|
||||
rval.consumed = 0; /* Context-free */ \
|
||||
return rval; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* The BER decoder of any type.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
ber_decode(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *type_descriptor, void **struct_ptr,
|
||||
const void *ptr, size_t size) {
|
||||
asn_codec_ctx_t s_codec_ctx;
|
||||
|
||||
/*
|
||||
* Stack checker requires that the codec context
|
||||
* must be allocated on the stack.
|
||||
*/
|
||||
if(opt_codec_ctx) {
|
||||
if(opt_codec_ctx->max_stack_size) {
|
||||
s_codec_ctx = *opt_codec_ctx;
|
||||
opt_codec_ctx = &s_codec_ctx;
|
||||
}
|
||||
} else {
|
||||
/* If context is not given, be security-conscious anyway */
|
||||
memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
|
||||
s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
|
||||
opt_codec_ctx = &s_codec_ctx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke type-specific decoder.
|
||||
*/
|
||||
return type_descriptor->op->ber_decoder(opt_codec_ctx, type_descriptor,
|
||||
struct_ptr, /* Pointer to the destination structure */
|
||||
ptr, size, /* Buffer and its size */
|
||||
0 /* Default tag mode is 0 */
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the set of <TL<TL<TL...>>> tags matches the definition.
|
||||
*/
|
||||
asn_dec_rval_t
|
||||
ber_check_tags(const asn_codec_ctx_t *opt_codec_ctx,
|
||||
const asn_TYPE_descriptor_t *td, asn_struct_ctx_t *opt_ctx,
|
||||
const void *ptr, size_t size, int tag_mode, int last_tag_form,
|
||||
ber_tlv_len_t *last_length, int *opt_tlv_form) {
|
||||
ssize_t consumed_myself = 0;
|
||||
ssize_t tag_len;
|
||||
ssize_t len_len;
|
||||
ber_tlv_tag_t tlv_tag;
|
||||
ber_tlv_len_t tlv_len;
|
||||
ber_tlv_len_t limit_len = -1;
|
||||
int expect_00_terminators = 0;
|
||||
int tlv_constr = -1; /* If CHOICE, opt_tlv_form is not given */
|
||||
int step = opt_ctx ? opt_ctx->step : 0; /* Where we left previously */
|
||||
int tagno;
|
||||
|
||||
/*
|
||||
* Make sure we didn't exceed the maximum stack size.
|
||||
*/
|
||||
if(ASN__STACK_OVERFLOW_CHECK(opt_codec_ctx))
|
||||
RETURN(RC_FAIL);
|
||||
|
||||
/*
|
||||
* So what does all this implicit skip stuff mean?
|
||||
* Imagine two types,
|
||||
* A ::= [5] IMPLICIT T
|
||||
* B ::= [2] EXPLICIT T
|
||||
* Where T is defined as
|
||||
* T ::= [4] IMPLICIT SEQUENCE { ... }
|
||||
*
|
||||
* Let's say, we are starting to decode type A, given the
|
||||
* following TLV stream: <5> <0>. What does this mean?
|
||||
* It means that the type A contains type T which is,
|
||||
* in turn, empty.
|
||||
* Remember though, that we are still in A. We cannot
|
||||
* just pass control to the type T decoder. Why? Because
|
||||
* the type T decoder expects <4> <0>, not <5> <0>.
|
||||
* So, we must make sure we are going to receive <5> while
|
||||
* still in A, then pass control to the T decoder, indicating
|
||||
* that the tag <4> was implicitly skipped. The decoder of T
|
||||
* hence will be prepared to treat <4> as valid tag, and decode
|
||||
* it appropriately.
|
||||
*/
|
||||
|
||||
tagno = step /* Continuing where left previously */
|
||||
+ (tag_mode==1?-1:0)
|
||||
;
|
||||
ASN_DEBUG("ber_check_tags(%s, size=%ld, tm=%d, step=%d, tagno=%d)",
|
||||
td->name, (long)size, tag_mode, step, tagno);
|
||||
/* assert(td->tags_count >= 1) May not be the case for CHOICE or ANY */
|
||||
|
||||
if(tag_mode == 0 && tagno == (int)td->tags_count) {
|
||||
/*
|
||||
* This must be the _untagged_ ANY type,
|
||||
* which outermost tag isn't known in advance.
|
||||
* Fetch the tag and length separately.
|
||||
*/
|
||||
tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
|
||||
switch(tag_len) {
|
||||
case -1: RETURN(RC_FAIL);
|
||||
case 0: RETURN(RC_WMORE);
|
||||
}
|
||||
tlv_constr = BER_TLV_CONSTRUCTED(ptr);
|
||||
len_len = ber_fetch_length(tlv_constr,
|
||||
(const char *)ptr + tag_len, size - tag_len, &tlv_len);
|
||||
switch(len_len) {
|
||||
case -1: RETURN(RC_FAIL);
|
||||
case 0: RETURN(RC_WMORE);
|
||||
}
|
||||
ASN_DEBUG("Advancing %ld in ANY case",
|
||||
(long)(tag_len + len_len));
|
||||
ADVANCE(tag_len + len_len);
|
||||
} else {
|
||||
assert(tagno < (int)td->tags_count); /* At least one loop */
|
||||
}
|
||||
for((void)tagno; tagno < (int)td->tags_count; tagno++, step++) {
|
||||
|
||||
/*
|
||||
* Fetch and process T from TLV.
|
||||
*/
|
||||
tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
|
||||
ASN_DEBUG("Fetching tag from {%p,%ld}: "
|
||||
"len %ld, step %d, tagno %d got %s",
|
||||
ptr, (long)size,
|
||||
(long)tag_len, step, tagno,
|
||||
ber_tlv_tag_string(tlv_tag));
|
||||
switch(tag_len) {
|
||||
case -1: RETURN(RC_FAIL);
|
||||
case 0: RETURN(RC_WMORE);
|
||||
}
|
||||
|
||||
tlv_constr = BER_TLV_CONSTRUCTED(ptr);
|
||||
|
||||
/*
|
||||
* If {I}, don't check anything.
|
||||
* If {I,B,C}, check B and C unless we're at I.
|
||||
*/
|
||||
if(tag_mode != 0 && step == 0) {
|
||||
/*
|
||||
* We don't expect tag to match here.
|
||||
* It's just because we don't know how the tag
|
||||
* is supposed to look like.
|
||||
*/
|
||||
} else {
|
||||
assert(tagno >= 0); /* Guaranteed by the code above */
|
||||
if(tlv_tag != td->tags[tagno]) {
|
||||
/*
|
||||
* Unexpected tag. Too bad.
|
||||
*/
|
||||
ASN_DEBUG("Expected: %s, "
|
||||
"expectation failed (tn=%d, tm=%d)",
|
||||
ber_tlv_tag_string(td->tags[tagno]),
|
||||
tagno, tag_mode
|
||||
);
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attention: if there are more tags expected,
|
||||
* ensure that the current tag is presented
|
||||
* in constructed form (it contains other tags!).
|
||||
* If this one is the last one, check that the tag form
|
||||
* matches the one given in descriptor.
|
||||
*/
|
||||
if(tagno < ((int)td->tags_count - 1)) {
|
||||
if(tlv_constr == 0) {
|
||||
ASN_DEBUG("tlv_constr = %d, expfail",
|
||||
tlv_constr);
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
} else {
|
||||
if(last_tag_form != tlv_constr
|
||||
&& last_tag_form != -1) {
|
||||
ASN_DEBUG("last_tag_form %d != %d",
|
||||
last_tag_form, tlv_constr);
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch and process L from TLV.
|
||||
*/
|
||||
len_len = ber_fetch_length(tlv_constr,
|
||||
(const char *)ptr + tag_len, size - tag_len, &tlv_len);
|
||||
ASN_DEBUG("Fetching len = %ld", (long)len_len);
|
||||
switch(len_len) {
|
||||
case -1: RETURN(RC_FAIL);
|
||||
case 0: RETURN(RC_WMORE);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME
|
||||
* As of today, the chain of tags
|
||||
* must either contain several indefinite length TLVs,
|
||||
* or several definite length ones.
|
||||
* No mixing is allowed.
|
||||
*/
|
||||
if(tlv_len == -1) {
|
||||
/*
|
||||
* Indefinite length.
|
||||
*/
|
||||
if(limit_len == -1) {
|
||||
expect_00_terminators++;
|
||||
} else {
|
||||
ASN_DEBUG("Unexpected indefinite length "
|
||||
"in a chain of definite lengths");
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
ADVANCE(tag_len + len_len);
|
||||
continue;
|
||||
} else {
|
||||
if(expect_00_terminators) {
|
||||
ASN_DEBUG("Unexpected definite length "
|
||||
"in a chain of indefinite lengths");
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that multiple TLVs specify ever decreasing length,
|
||||
* which is consistent.
|
||||
*/
|
||||
if(limit_len == -1) {
|
||||
limit_len = tlv_len + tag_len + len_len;
|
||||
if(limit_len < 0) {
|
||||
/* Too great tlv_len value? */
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
} else if(limit_len != tlv_len + tag_len + len_len) {
|
||||
/*
|
||||
* Inner TLV specifies length which is inconsistent
|
||||
* with the outer TLV's length value.
|
||||
*/
|
||||
ASN_DEBUG("Outer TLV is %ld and inner is %ld",
|
||||
(long)limit_len, (long)tlv_len);
|
||||
RETURN(RC_FAIL);
|
||||
}
|
||||
|
||||
ADVANCE(tag_len + len_len);
|
||||
|
||||
limit_len -= (tag_len + len_len);
|
||||
if((ssize_t)size > limit_len) {
|
||||
/*
|
||||
* Make sure that we won't consume more bytes
|
||||
* from the parent frame than the inferred limit.
|
||||
*/
|
||||
size = limit_len;
|
||||
}
|
||||
}
|
||||
|
||||
if(opt_tlv_form)
|
||||
*opt_tlv_form = tlv_constr;
|
||||
if(expect_00_terminators)
|
||||
*last_length = -expect_00_terminators;
|
||||
else
|
||||
*last_length = tlv_len;
|
||||
|
||||
RETURN(RC_OK);
|
||||
}
|
||||