From 27f76bb794af89f5ed9088317fc2e82247667f74 Mon Sep 17 00:00:00 2001 From: erititan <elemer.lelik@ericsson.com> Date: Thu, 1 Jun 2017 13:23:49 +0200 Subject: [PATCH] R30A --- TCCUsefulFunctions_CNL113472_Common.tpd | 12 +- TCCUsefulFunctions_CNL113472_IPsec.tpd | 18 +- TCCUsefulFunctions_CNL113472_Interface.tpd | 12 +- TCCUsefulFunctions_CNL113472_Maths.tpd | 12 +- TCCUsefulFunctions_CNL113472_OpenSecurity.tpd | 46 + ...nctions_CNL113472_PermutatedParameters.tpd | 12 +- TCCUsefulFunctions_CNL113472_Regexp.tpd | 13 +- TCCUsefulFunctions_CNL113472_TitanSim.tpd | 13 +- TCCUsefulFunctions_CNL113472_XPath.tpd | 13 +- demo/TCCAssertion_Example.ttcn | 18 +- demo/TCCConversion_Example.ttcn | 20 +- demo/TCCDateTime_Example.ttcn | 18 +- demo/TCCEncoding_Example.ttcn | 20 +- demo/TCCEnv_Example.ttcn | 18 +- demo/TCCFileIO_Example.ttcn | 18 +- demo/TCCFileSystem_Example.ttcn | 18 +- demo/TCCIPsec_Example.ttcn | 18 +- demo/TCCInterface_Example.ttcn | 18 +- demo/TCCMaths_Example.ttcn | 359 ++++-- demo/TCCMessageHandling_Example.ttcn | 17 +- demo/TCCPermutatedParameters_Example.ttcn | 16 +- demo/TCCRegexp_Example.ttcn | 52 + demo/TCCTemplate_Example.ttcn | 18 +- demo/TCCTitanMetadata_Example.ttcn | 18 +- demo/TCCXPathSupport_Example.ttcn | 18 +- doc/TCCUsefulFunctions_CNL113472_1551.doc | Bin 391680 -> 402432 bytes doc/TCCUsefulFunctions_CNL113472_PRI.doc | Bin 143360 -> 156160 bytes doc/apidoc/Data/ClassHierarchy.nd | Bin doc/apidoc/Data/ConfigFileInfo.nd | Bin doc/apidoc/Data/FileInfo.nd | 0 doc/apidoc/Data/ImageFileInfo.nd | Bin doc/apidoc/Data/ImageReferenceTable.nd | Bin doc/apidoc/Data/IndexInfo.nd | Bin doc/apidoc/Data/PreviousMenuState.nd | Bin doc/apidoc/Data/PreviousSettings.nd | Bin doc/apidoc/Data/SymbolTable.nd | Bin doc/apidoc/Menu.txt | 0 doc/apidoc/Menu.txt~ | 165 --- doc/apidoc/html/index.html~ | 21 - doc/apidoc/html/javascript/main.js | 0 doc/apidoc/html/javascript/searchdata.js | 0 doc/apidoc/html/menu.html~ | 254 ---- doc/apidoc/html/styles/1.css | 0 doc/apidoc/html/styles/2.css | 0 doc/apidoc/html/styles/main.css | 0 src/TCCAssertion.cc | 19 +- src/TCCAssertion_Functions.ttcn | 19 +- src/TCCConversion.cc | 19 +- src/TCCConversion_Functions.ttcn | 20 +- src/TCCDateTime.cc | 19 +- src/TCCDateTime_Functions.ttcn | 19 +- src/TCCEncoding.cc | 19 +- src/TCCEncoding_Functions.ttcn | 21 +- src/TCCEnv.cc | 19 +- src/TCCEnv_Functions.ttcn | 19 +- src/TCCFileIO.cc | 78 +- src/TCCFileIO_Functions.ttcn | 83 +- src/TCCFileSystem.cc | 19 +- src/TCCFileSystem_Functions.ttcn | 19 +- src/TCCIPsec.cc | 19 +- src/TCCIPsec_Definitions.ttcn | 19 +- src/TCCIPsec_Functions.ttcn | 18 +- src/TCCIPsec_XFRM.cc | 358 ++++++ src/TCCIPsec_XFRM.hh | 34 + src/TCCIPsec_XFRM_Definitions.ttcn | 578 +++++++++ src/TCCIPsec_XFRM_SA.cc | 324 +++++ src/TCCIPsec_XFRM_SP.cc | 264 ++++ src/TCCInterface.cc | 19 +- src/TCCInterface_Functions.ttcn | 19 +- src/TCCInterface_ip.h | 23 +- src/TCCMaths.cc | 411 +++--- src/TCCMaths_Functions.ttcn | 19 +- src/TCCMaths_GenericTypes.ttcn | 19 +- src/TCCMessageHandling.cc | 18 +- src/TCCMessageHandling_Functions.ttcn | 19 +- src/TCCOpenSecurity.cc | 1128 +++++++++++++++++ src/TCCOpenSecurity_Functions.ttcn | 585 +++++++++ src/TCCPermutatedParameters_Definitions.ttcn | 21 +- src/TCCPermutatedParameters_Functions.ttcn | 21 +- src/TCCRegexp.cc | 75 +- src/TCCRegexp_Functions.ttcn | 50 +- src/TCCSystem.cc | 19 +- src/TCCSystem_Functions.ttcn | 19 +- src/TCCTemplate_Functions.ttcn | 19 +- src/TCCTitanMetadata.cc | 19 +- src/TCCTitanMetadata_Functions.ttcn | 19 +- src/TCCUsefulFunctions_Library.grp | 24 +- ...CCUsefulFunctions_PermutatedParameters.grp | 19 +- src/TCCXPathSupport.cc | 19 +- src/TCCXPathSupport_Functions.ttcn | 19 +- 90 files changed, 4538 insertions(+), 1326 deletions(-) create mode 100644 TCCUsefulFunctions_CNL113472_OpenSecurity.tpd create mode 100644 demo/TCCRegexp_Example.ttcn mode change 100644 => 100755 doc/apidoc/Data/ClassHierarchy.nd mode change 100644 => 100755 doc/apidoc/Data/ConfigFileInfo.nd mode change 100644 => 100755 doc/apidoc/Data/FileInfo.nd mode change 100644 => 100755 doc/apidoc/Data/ImageFileInfo.nd mode change 100644 => 100755 doc/apidoc/Data/ImageReferenceTable.nd mode change 100644 => 100755 doc/apidoc/Data/IndexInfo.nd mode change 100644 => 100755 doc/apidoc/Data/PreviousMenuState.nd mode change 100644 => 100755 doc/apidoc/Data/PreviousSettings.nd mode change 100644 => 100755 doc/apidoc/Data/SymbolTable.nd mode change 100644 => 100755 doc/apidoc/Menu.txt delete mode 100644 doc/apidoc/Menu.txt~ delete mode 100644 doc/apidoc/html/index.html~ mode change 100644 => 100755 doc/apidoc/html/javascript/main.js mode change 100644 => 100755 doc/apidoc/html/javascript/searchdata.js delete mode 100644 doc/apidoc/html/menu.html~ mode change 100644 => 100755 doc/apidoc/html/styles/1.css mode change 100644 => 100755 doc/apidoc/html/styles/2.css mode change 100644 => 100755 doc/apidoc/html/styles/main.css create mode 100644 src/TCCIPsec_XFRM.cc create mode 100644 src/TCCIPsec_XFRM.hh create mode 100644 src/TCCIPsec_XFRM_Definitions.ttcn create mode 100644 src/TCCIPsec_XFRM_SA.cc create mode 100644 src/TCCIPsec_XFRM_SP.cc create mode 100644 src/TCCOpenSecurity.cc create mode 100644 src/TCCOpenSecurity_Functions.ttcn diff --git a/TCCUsefulFunctions_CNL113472_Common.tpd b/TCCUsefulFunctions_CNL113472_Common.tpd index 6588123..f13aed5 100644 --- a/TCCUsefulFunctions_CNL113472_Common.tpd +++ b/TCCUsefulFunctions_CNL113472_Common.tpd @@ -1,16 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (c) 2016 Ericsson + Copyright (c) 2017 Ericsson - The copyright to the computer program(s) herein is the property of Ericsson. - The program(s) may be used and/or copied only with the written permission - of Ericsson or in accordance with the terms and conditions stipulated in the - agreement/contract under which the program(s) has been supplied. + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html File: TCCUsefulFunctions_CNL113472_Common.tpd Description: tpd project file - Rev: R25A + Rev: R30A Prodnr: CNL 113 472 --> diff --git a/TCCUsefulFunctions_CNL113472_IPsec.tpd b/TCCUsefulFunctions_CNL113472_IPsec.tpd index ae7601c..de94e2e 100644 --- a/TCCUsefulFunctions_CNL113472_IPsec.tpd +++ b/TCCUsefulFunctions_CNL113472_IPsec.tpd @@ -1,16 +1,17 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (c) 2016 Ericsson + Copyright (c) 2017 Ericsson + + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html - The copyright to the computer program(s) herein is the property of Ericsson. - The program(s) may be used and/or copied only with the written permission - of Ericsson or in accordance with the terms and conditions stipulated in the - agreement/contract under which the program(s) has been supplied. File: TCCUsefulFunctions_CNL113472_IPsec.tpd Description: tpd project file - Rev: R25A + Rev: R30A Prodnr: CNL 113 472 --> @@ -20,6 +21,11 @@ <FileResource projectRelativePath="TCCIPsec.cc" relativeURI="src/TCCIPsec.cc"/> <FileResource projectRelativePath="TCCIPsec_Definitions.ttcn" relativeURI="src/TCCIPsec_Definitions.ttcn"/> <FileResource projectRelativePath="TCCIPsec_Functions.ttcn" relativeURI="src/TCCIPsec_Functions.ttcn"/> + <FileResource projectRelativePath="TCCIPsec_XFRM.cc" relativeURI="src/TCCIPsec_XFRM.cc"/> + <FileResource projectRelativePath="TCCIPsec_XFRM.hh" relativeURI="src/TCCIPsec_XFRM.hh"/> + <FileResource projectRelativePath="TCCIPsec_XFRM_Definitions.ttcn" relativeURI="src/TCCIPsec_XFRM_Definitions.ttcn"/> + <FileResource projectRelativePath="TCCIPsec_XFRM_SA.cc" relativeURI="src/TCCIPsec_XFRM_SA.cc"/> + <FileResource projectRelativePath="TCCIPsec_XFRM_SP.cc" relativeURI="src/TCCIPsec_XFRM_SP.cc"/> </Files> <ActiveConfiguration>KAME_IPSEC</ActiveConfiguration> <Configurations> diff --git a/TCCUsefulFunctions_CNL113472_Interface.tpd b/TCCUsefulFunctions_CNL113472_Interface.tpd index a669755..d852adf 100644 --- a/TCCUsefulFunctions_CNL113472_Interface.tpd +++ b/TCCUsefulFunctions_CNL113472_Interface.tpd @@ -1,16 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (c) 2016 Ericsson + Copyright (c) 2017 Ericsson - The copyright to the computer program(s) herein is the property of Ericsson. - The program(s) may be used and/or copied only with the written permission - of Ericsson or in accordance with the terms and conditions stipulated in the - agreement/contract under which the program(s) has been supplied. + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html File: TCCUsefulFunctions_CNL113472_Interface.tpd Description: tpd project file - Rev: R25A + Rev: R30A Prodnr: CNL 113 472 --> diff --git a/TCCUsefulFunctions_CNL113472_Maths.tpd b/TCCUsefulFunctions_CNL113472_Maths.tpd index c9fa16e..a89ba9a 100644 --- a/TCCUsefulFunctions_CNL113472_Maths.tpd +++ b/TCCUsefulFunctions_CNL113472_Maths.tpd @@ -1,16 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (c) 2016 Ericsson + Copyright (c) 2017 Ericsson - The copyright to the computer program(s) herein is the property of Ericsson. - The program(s) may be used and/or copied only with the written permission - of Ericsson or in accordance with the terms and conditions stipulated in the - agreement/contract under which the program(s) has been supplied. + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html File: TCCUsefulFunctions_CNL113472_Maths.tpd Description: tpd project file - Rev: R25A + Rev: R30A Prodnr: CNL 113 472 --> diff --git a/TCCUsefulFunctions_CNL113472_OpenSecurity.tpd b/TCCUsefulFunctions_CNL113472_OpenSecurity.tpd new file mode 100644 index 0000000..d3143d5 --- /dev/null +++ b/TCCUsefulFunctions_CNL113472_OpenSecurity.tpd @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2017 Ericsson + + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html + + + + File: TCCUsefulFunctions_CNL113472_OpenSecurity.tpd + Description: tpd project file + Rev: R30A + Prodnr: CNL 113 472 + + --> +<TITAN_Project_File_Information version="1.0"> + <ProjectName>TCCUsefulFunctions_CNL113472_OpenSecurity</ProjectName> + <Files> + <FileResource projectRelativePath="TCCOpenSecurity.cc" relativeURI="src/TCCOpenSecurity.cc"/> + <FileResource projectRelativePath="TCCOpenSecurity_Functions.ttcn" relativeURI="src/TCCOpenSecurity_Functions.ttcn"/> + </Files> + <ActiveConfiguration>Default</ActiveConfiguration> + <Configurations> + <Configuration name="Default"> + <ProjectProperties> + <MakefileSettings> + <generateInternalMakefile>true</generateInternalMakefile> + <GNUMake>true</GNUMake> + <incrementalDependencyRefresh>true</incrementalDependencyRefresh> + <targetExecutable>bin/TCCUsefulFunctions_CNL113472_Security</targetExecutable> + <buildLevel>Level 3 - Creating object files with dependency update</buildLevel> + </MakefileSettings> + <LocalBuildSettings> + <workingDirectory>bin</workingDirectory> + </LocalBuildSettings> + <NamingCoventions> + <enableProjectSpecificSettings>true</enableProjectSpecificSettings> + <externalFunction>.*</externalFunction> + <formalParameter>.*</formalParameter> + </NamingCoventions> + </ProjectProperties> + </Configuration> + </Configurations> +</TITAN_Project_File_Information> diff --git a/TCCUsefulFunctions_CNL113472_PermutatedParameters.tpd b/TCCUsefulFunctions_CNL113472_PermutatedParameters.tpd index 7ff0eca..73208fc 100644 --- a/TCCUsefulFunctions_CNL113472_PermutatedParameters.tpd +++ b/TCCUsefulFunctions_CNL113472_PermutatedParameters.tpd @@ -1,16 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (c) 2016 Ericsson + Copyright (c) 2017 Ericsson - The copyright to the computer program(s) herein is the property of Ericsson. - The program(s) may be used and/or copied only with the written permission - of Ericsson or in accordance with the terms and conditions stipulated in the - agreement/contract under which the program(s) has been supplied. + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html File: TCCUsefulFunctions_CNL113472_PermutatedParameters.tpd Description: tpd project file - Rev: R25A + Rev: R30A Prodnr: CNL 113 472 --> diff --git a/TCCUsefulFunctions_CNL113472_Regexp.tpd b/TCCUsefulFunctions_CNL113472_Regexp.tpd index 3e996cf..13b3d93 100644 --- a/TCCUsefulFunctions_CNL113472_Regexp.tpd +++ b/TCCUsefulFunctions_CNL113472_Regexp.tpd @@ -1,16 +1,17 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (c) 2016 Ericsson + Copyright (c) 2017 Ericsson + + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html - The copyright to the computer program(s) herein is the property of Ericsson. - The program(s) may be used and/or copied only with the written permission - of Ericsson or in accordance with the terms and conditions stipulated in the - agreement/contract under which the program(s) has been supplied. File: TCCUsefulFunctions_CNL113472_Regexp.tpd Description: tpd project file - Rev: R25A + Rev: R30A Prodnr: CNL 113 472 --> diff --git a/TCCUsefulFunctions_CNL113472_TitanSim.tpd b/TCCUsefulFunctions_CNL113472_TitanSim.tpd index 2a775d0..74539c0 100644 --- a/TCCUsefulFunctions_CNL113472_TitanSim.tpd +++ b/TCCUsefulFunctions_CNL113472_TitanSim.tpd @@ -1,16 +1,17 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (c) 2016 Ericsson + Copyright (c) 2017 Ericsson + + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html - The copyright to the computer program(s) herein is the property of Ericsson. - The program(s) may be used and/or copied only with the written permission - of Ericsson or in accordance with the terms and conditions stipulated in the - agreement/contract under which the program(s) has been supplied. File: TCCUsefulFunctions_CNL113472_TitanSim.tpd Description: tpd project file - Rev: R25A + Rev: R30A Prodnr: CNL 113 472 --> diff --git a/TCCUsefulFunctions_CNL113472_XPath.tpd b/TCCUsefulFunctions_CNL113472_XPath.tpd index 4043c34..2bf643f 100644 --- a/TCCUsefulFunctions_CNL113472_XPath.tpd +++ b/TCCUsefulFunctions_CNL113472_XPath.tpd @@ -1,16 +1,17 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (c) 2016 Ericsson + Copyright (c) 2017 Ericsson + + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html - The copyright to the computer program(s) herein is the property of Ericsson. - The program(s) may be used and/or copied only with the written permission - of Ericsson or in accordance with the terms and conditions stipulated in the - agreement/contract under which the program(s) has been supplied. File: TCCUsefulFunctions_CNL113472_XPath.tpd Description: tpd project file - Rev: R25A + Rev: R30A Prodnr: CNL 113 472 --> diff --git a/demo/TCCAssertion_Example.ttcn b/demo/TCCAssertion_Example.ttcn index 436e24a..a600570 100644 --- a/demo/TCCAssertion_Example.ttcn +++ b/demo/TCCAssertion_Example.ttcn @@ -1,16 +1,16 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCAssertion_Example.ttcn // Description: TCC Useful Functions: Assertion Functions. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2007-11-14 // Contact: http://ttcn.ericsson.se diff --git a/demo/TCCConversion_Example.ttcn b/demo/TCCConversion_Example.ttcn index 34cf117..4dca33a 100644 --- a/demo/TCCConversion_Example.ttcn +++ b/demo/TCCConversion_Example.ttcn @@ -1,16 +1,16 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCConversion_Example.ttcn // Description: TCC Useful Functions: Conversion Functions. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2013-09-24 // Contact: http://ttcn.ericsson.se @@ -248,6 +248,6 @@ control }//end of module with { -extension "version R22B" +extension "version R30A" } diff --git a/demo/TCCDateTime_Example.ttcn b/demo/TCCDateTime_Example.ttcn index 14f7110..37880f5 100644 --- a/demo/TCCDateTime_Example.ttcn +++ b/demo/TCCDateTime_Example.ttcn @@ -1,16 +1,16 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCDateTime_Example.ttcn // Description: TCC Useful testcases: DateTime testcases. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2011-05-30 // Contact: http://ttcn.ericsson.se diff --git a/demo/TCCEncoding_Example.ttcn b/demo/TCCEncoding_Example.ttcn index 838b416..9b192c7 100644 --- a/demo/TCCEncoding_Example.ttcn +++ b/demo/TCCEncoding_Example.ttcn @@ -1,16 +1,16 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCEncoding_Example.ttcn // Description: TCC Useful Functions: Message Encoding Functions. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2013-02-05 // Contact: http://ttcn.ericsson.se @@ -151,5 +151,5 @@ control { execute(tc_005_artf265694()); } -} with {extension "version R22B"} +} with {extension "version R30A"} diff --git a/demo/TCCEnv_Example.ttcn b/demo/TCCEnv_Example.ttcn index 9df673a..1ca5b58 100644 --- a/demo/TCCEnv_Example.ttcn +++ b/demo/TCCEnv_Example.ttcn @@ -1,16 +1,16 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCEnv_Example.ttcn // Description: TCC Useful Functions: Environment Handling Functions. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2008-12-10 // Contact: http://ttcn.ericsson.se diff --git a/demo/TCCFileIO_Example.ttcn b/demo/TCCFileIO_Example.ttcn index 0346d13..2fb9dac 100644 --- a/demo/TCCFileIO_Example.ttcn +++ b/demo/TCCFileIO_Example.ttcn @@ -1,16 +1,16 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCFileIO_Example.ttcn // Description: TCC Useful Functions: File IO Functions. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2008-12-10 // Contact: http://ttcn.ericsson.se diff --git a/demo/TCCFileSystem_Example.ttcn b/demo/TCCFileSystem_Example.ttcn index de4c5c2..2013c8e 100644 --- a/demo/TCCFileSystem_Example.ttcn +++ b/demo/TCCFileSystem_Example.ttcn @@ -1,16 +1,16 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCFileSystem_Example.ttcn // Description: TCC Useful testcases: FileSystem testcases. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2011-07-14 // Contact: http://ttcn.ericsson.se diff --git a/demo/TCCIPsec_Example.ttcn b/demo/TCCIPsec_Example.ttcn index 469870d..121fdd0 100644 --- a/demo/TCCIPsec_Example.ttcn +++ b/demo/TCCIPsec_Example.ttcn @@ -1,16 +1,16 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCAssertion_Example.ttcn // Description: TCC Useful Functions: Assertion Functions. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2013-01-09 // Contact: http://ttcn.ericsson.se diff --git a/demo/TCCInterface_Example.ttcn b/demo/TCCInterface_Example.ttcn index 6626d03..7f8f1e7 100644 --- a/demo/TCCInterface_Example.ttcn +++ b/demo/TCCInterface_Example.ttcn @@ -1,16 +1,16 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCInterface_Example.ttcn // Description: TCC Useful Functions: Interface Functions. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2008-12-10 // Contact: http://ttcn.ericsson.se diff --git a/demo/TCCMaths_Example.ttcn b/demo/TCCMaths_Example.ttcn index 4221e74..571d13f 100644 --- a/demo/TCCMaths_Example.ttcn +++ b/demo/TCCMaths_Example.ttcn @@ -1,22 +1,22 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCMaths_Example.ttcn // Description: TCC Useful testcases: Maths testcases. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2007-12-09 // Contact: http://ttcn.ericsson.se /////////////////////////////////////////////// -module TCCMaths_Example +module TCCMaths_Example { import from TCCMaths_Functions all; @@ -24,31 +24,40 @@ import from TCCMaths_GenericTypes all; modulepar float LIMIT := 0.01; -type component Maths_CT { +type component Maths_CT { // math var float tmpFloat; var integer tmpInt; var float sum; + var float resFZero := 0.0; // integer var IntegerList ilist1 := { 1, 2, 3, 4, 5}; var IntegerList ilist2 := { 6, 7, 8, 9, 10}; + var IntegerList ilist_one_value := {42}; + var IntegerList ilist_empty := {}; + var IntegerList ilist_unbound; var IntegerList ires; var IntegerList maxIL1 := {5, 4}; var IntegerList minIL1 := {1, 0}; + var IntegerList errIL := {0, -1}; var float avgIL1 := 3.0; var IntegerList updIL1 := { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; var float stdIL1 := 1.581139; - var float stdILL1 := 1.581139; + var float stdILL1 := 1.581139; // float var FloatList flist1 := { 1.0, 2.0, 3.0, 4.0, 5.0}; var FloatList flist2 := { 6.0, 7.0, 8.0, 9.0, 10.0}; + var FloatList flist_one_value := {42.0}; + var FloatList flist_empty := {}; + var FloatList flist_unbound; var FloatList fres; var FloatList maxFL1 := {5.0, 4.0}; var FloatList minFL1 := {1.0, 0.0}; + var FloatList errFL := {0.0, -1.0}; var float avgFL1 := 3.0; var FloatList updFL1 := { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}; var float stdFL1 := 1.58; @@ -88,6 +97,20 @@ testcase f_test_maxIL() runs on Maths_CT if (ires == maxIL1) { setverdict(pass); } else { setverdict(fail); } + + log("Max of empty integer list"); + ires := f_maxIL(ilist_empty); + log("MaxIL (maxVal, maxIdx): ", ires); + + if (ires == errIL) { setverdict(pass); } + else { setverdict(fail); } + + log("Max of unbound integer list"); + ires := f_maxIL(ilist_unbound); + log("MaxIL (maxVal, maxIdx): ", ires); + + if (ires == errIL) { setverdict(pass); } + else { setverdict(fail); } } // test f_minIL testcase @@ -107,6 +130,20 @@ testcase f_test_minIL() runs on Maths_CT if (ires == minIL1) { setverdict(pass); } else { setverdict(fail); } + + log("Min of empty integer list"); + ires := f_minIL(ilist_empty); + log("MinIL (minVal, minIdx): ", ires); + + if (ires == errIL) { setverdict(pass); } + else { setverdict(fail); } + + log("Min of unbound integer list"); + ires := f_minIL(ilist_unbound); + log("MinIL (minVal, minIdx): ", ires); + + if (ires == errIL) { setverdict(pass); } + else { setverdict(fail); } } // test f_averageIL testcase @@ -122,10 +159,28 @@ testcase f_test_averageIL() runs on Maths_CT log(" ----------- f_averageIL ----------- "); log("Original integer list: ", ilist1); tmpFloat := f_averageIL(ilist1); - log("AverageIL (averageVal, averageIdx): ", tmpFloat); + log("AverageIL: ", tmpFloat); if (tmpFloat == avgIL1) { setverdict(pass); } else { setverdict(fail); } + + log("Average for one value list"); + tmpFloat := f_averageIL(ilist_one_value); + log("AverageIL: ", tmpFloat); + if (tmpFloat == int2float(ilist_one_value[0])) { setverdict(pass); } + else { setverdict(fail); } + + log("Average for empty list"); + tmpFloat := f_averageIL(ilist_empty); + log("AverageIL: ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } + + log("Average for unbound list"); + tmpFloat := f_averageIL(ilist_unbound); + log("AverageIL: ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } } // test f_averageIL testcase @@ -164,12 +219,30 @@ testcase f_test_stdIL() runs on Maths_CT tmpFloat := f_stdIL(ilist1); log("Normalized, standard derivation (IL): ", tmpFloat); - if ((tmpFloat - stdIL1) * (tmpFloat - stdIL1) < LIMIT) { - setverdict(pass); + if ((tmpFloat - stdIL1) * (tmpFloat - stdIL1) < LIMIT) { + setverdict(pass); } - else { - setverdict(fail); + else { + setverdict(fail); } + + log("Normalized, standard derivation for one value list"); + tmpFloat := f_stdIL(ilist_one_value); + log("Normalized, standard derivation (IL): ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } + + log("Normalized, standard derivation for empty list"); + tmpFloat := f_stdIL(ilist_empty); + log("Normalized, standard derivation (IL): ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } + + log("Normalized, standard derivation for unbound list"); + tmpFloat := f_stdIL(ilist_unbound); + log("Normalized, standard derivation (IL): ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } } // test f_averageILL testcase @@ -187,12 +260,30 @@ testcase f_test_stdILL() runs on Maths_CT tmpFloat := f_stdILL(ilist1, f_averageIL(ilist1)); log("Normalized, standard derivation (ILL): ", tmpFloat); - if ((tmpFloat - stdILL1) * (tmpFloat - stdILL1) < LIMIT) { - setverdict(pass); + if ((tmpFloat - stdILL1) * (tmpFloat - stdILL1) < LIMIT) { + setverdict(pass); } - else { - setverdict(fail); + else { + setverdict(fail); } + + log("Normalized, standard derivation for one value list"); + tmpFloat := f_stdILL(ilist_one_value, f_averageIL(ilist1)); + log("Normalized, standard derivation (IL): ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } + + log("Normalized, standard derivation for empty list"); + tmpFloat := f_stdILL(ilist_empty, f_averageIL(ilist1)); + log("Normalized, standard derivation (IL): ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } + + log("Normalized, standard derivation for unbound list"); + tmpFloat := f_stdILL(ilist_unbound, f_averageIL(ilist1)); + log("Normalized, standard derivation (IL): ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } } // test f_maxIL testcase @@ -212,6 +303,20 @@ testcase f_test_maxFL() runs on Maths_CT if (fres == maxFL1) { setverdict(pass); } else { setverdict(fail); } + + log("Max of empty float list"); + fres := f_maxFL(flist_empty); + log("MaxFL (maxVal, maxIdx): ", fres); + + if (fres == errFL) { setverdict(pass); } + else { setverdict(fail); } + + log("Max of unbound float list"); + fres := f_maxFL(flist_unbound); + log("MaxFL (maxVal, maxIdx): ", fres); + + if (fres == errFL) { setverdict(pass); } + else { setverdict(fail); } } // test f_minIL testcase @@ -227,10 +332,24 @@ testcase f_test_minFL() runs on Maths_CT log(" ----------- f_minFL ----------- "); log("Original float list: ", flist1); fres := f_minFL(flist1); - log("MinIL (minVal, minIdx): ", fres); + log("MinFL (minVal, minIdx): ", fres); if (fres == minFL1) { setverdict(pass); } else { setverdict(fail); } + + log("Min of empty float list"); + fres := f_minFL(flist_empty); + log("MinFL (minVal, minIdx): ", fres); + + if (fres == errFL) { setverdict(pass); } + else { setverdict(fail); } + + log("Min of unbound float list"); + fres := f_minFL(flist_unbound); + log("MinFL (minVal, minIdx): ", fres); + + if (fres == errFL) { setverdict(pass); } + else { setverdict(fail); } } // test f_averageIL testcase @@ -245,11 +364,29 @@ testcase f_test_averageFL() runs on Maths_CT log(" ----------- f_averageFL ----------- "); log("Original float list: ", flist1); - tmpFloat := f_averageFL(flist1); - log("AverageIL (averageVal, averageIdx): ", tmpFloat); + tmpFloat := f_averageFL(flist1); + log("AverageFL: ", tmpFloat); if (tmpFloat == avgFL1) { setverdict(pass); } else { setverdict(fail); } + + log("Average for one value list"); + tmpFloat := f_averageFL(flist_one_value); + log("AverageFL: ", tmpFloat); + if (tmpFloat == flist_one_value[0]) { setverdict(pass); } + else { setverdict(fail); } + + log("Average for empty list"); + tmpFloat := f_averageFL(flist_empty); + log("AverageFL: ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } + + log("Average for unbound list"); + tmpFloat := f_averageFL(flist_unbound); + log("AverageFL: ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } } // test f_averageIL testcase @@ -286,14 +423,32 @@ testcase f_test_stdFL() runs on Maths_CT log(" ----------- f_stdFL ----------- "); log("Original float list: ", flist1); tmpFloat := f_stdFL(flist1); - log("Normalized, standard derivation (IL): ", tmpFloat); + log("Normalized, standard derivation (FL): ", tmpFloat); - if ((tmpFloat - stdFL1) * (tmpFloat - stdFL1) < LIMIT) { - setverdict(pass); + if ((tmpFloat - stdFL1) * (tmpFloat - stdFL1) < LIMIT) { + setverdict(pass); } - else { - setverdict(fail); + else { + setverdict(fail); } + + log("Normalized, standard derivation for one value list"); + tmpFloat := f_stdFL(flist_one_value); + log("Normalized, standard derivation (FL): ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } + + log("Normalized, standard derivation for empty list"); + tmpFloat := f_stdFL(flist_empty); + log("Normalized, standard derivation (FL): ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } + + log("Normalized, standard derivation for unbound list"); + tmpFloat := f_stdFL(flist_unbound); + log("Normalized, standard derivation (FL): ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } } // test f_averageFLL testcase @@ -311,11 +466,29 @@ testcase f_test_stdFLL() runs on Maths_CT tmpFloat := f_stdFLL(flist1, f_averageFL(flist1)); log("Normalized, standard derivation (FLL): ", tmpFloat); - if ((tmpFloat - stdFLL1) * (tmpFloat - stdFLL1) < LIMIT) { - setverdict(pass); + if ((tmpFloat - stdFLL1) * (tmpFloat - stdFLL1) < LIMIT) { + setverdict(pass); } - else { - setverdict(fail); + else { + setverdict(fail); + + log("Normalized, standard derivation for one value list"); + tmpFloat := f_stdFLL(flist_one_value, f_averageFL(flist1)); + log("Normalized, standard derivation (FL): ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } + + log("Normalized, standard derivation for empty list"); + tmpFloat := f_stdFLL(flist_empty, f_averageFL(flist1)); + log("Normalized, standard derivation (FL): ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } + + log("Normalized, standard derivation for unbound list"); + tmpFloat := f_stdFLL(flist_unbound, f_averageFL(flist1)); + log("Normalized, standard derivation (FL): ", tmpFloat); + if (tmpFloat == resFZero) { setverdict(pass); } + else { setverdict(fail); } } } @@ -323,10 +496,10 @@ testcase f_test_stdFLL() runs on Maths_CT testcase f_test_sinVL() runs on Maths_CT { log(" ----------- f_sinVL ----------- "); - log("SINUS (Frequency: ", freq, - ", altitude: ", alti, - ", startval: ", startval, - ", step: ", step, + log("SINUS (Frequency: ", freq, + ", altitude: ", alti, + ", startval: ", startval, + ", step: ", step, ", return length: ", len, "):"); fres := f_sinVL(freq, alti, startval, len, step); @@ -347,10 +520,10 @@ testcase f_test_sinVL() runs on Maths_CT testcase f_test_cosVL() runs on Maths_CT { log(" ----------- f_cosVL ----------- "); - log("COSINUS (Frequency: ", freq, - ", altitude: ", alti, - ", startval: ", startval, - ", step: ", step, + log("COSINUS (Frequency: ", freq, + ", altitude: ", alti, + ", startval: ", startval, + ", step: ", step, ", return length: ", len, "):"); fres := f_cosVL(freq, alti, startval, len, step); @@ -364,7 +537,7 @@ testcase f_test_cosVL() runs on Maths_CT sum := sum + tmpFloat * tmpFloat; } if (sum < LIMIT) { setverdict(pass); } - else { setverdict(fail); } + else { setverdict(fail); } } // test function pi @@ -380,7 +553,7 @@ testcase f_test_pi() runs on Maths_CT testcase f_test_sin() runs on Maths_CT { log(" ----------- f_sin ----------- "); - + tmpFloat := f_sin(3.1415926535 / 2.0); log("Sine of PI/2: ", tmpFloat); @@ -392,7 +565,7 @@ testcase f_test_sin() runs on Maths_CT testcase f_test_cos() runs on Maths_CT { log(" ----------- f_cos ----------- "); - + tmpFloat := f_cos(3.1415926535 / 2.0); log("Cosine of PI/2: ", tmpFloat); @@ -403,13 +576,13 @@ testcase f_test_cos() runs on Maths_CT testcase f_test_asin() runs on Maths_CT { log(" ----------- f_asin ----------- "); - + tmpFloat := f_asin(1.0); log("Arc sine of 1.0: ", tmpFloat); tmpFloat := tmpFloat - 3.1415926535 / 2.0; - if (tmpFloat * tmpFloat < LIMIT ) { - setverdict(pass); + if (tmpFloat * tmpFloat < LIMIT ) { + setverdict(pass); } else { setverdict(fail); } } @@ -417,13 +590,13 @@ testcase f_test_asin() runs on Maths_CT testcase f_test_acos() runs on Maths_CT { log(" ----------- f_acos ----------- "); - + tmpFloat := f_acos(0.0); log("Arc cosine of 0.0: ", tmpFloat); tmpFloat := tmpFloat - 3.1415926535 / 2.0; - if (tmpFloat * tmpFloat < LIMIT) { - setverdict(pass); + if (tmpFloat * tmpFloat < LIMIT) { + setverdict(pass); } else { setverdict(fail); } } @@ -431,13 +604,13 @@ testcase f_test_acos() runs on Maths_CT testcase f_test_powFF() runs on Maths_CT { log(" ----------- f_powFF ----------- "); - + tmpFloat := f_powFF(2.0, 3.0); log("Raise 2.0 to power 3.0: ", tmpFloat); tmpFloat := tmpFloat - 8.0; - if ( tmpFloat * tmpFloat < LIMIT) { - setverdict(pass); + if ( tmpFloat * tmpFloat < LIMIT) { + setverdict(pass); } else { setverdict(fail); } } @@ -445,12 +618,12 @@ testcase f_test_powFF() runs on Maths_CT testcase f_test_powII() runs on Maths_CT { log(" ----------- f_powII ----------- "); - + tmpInt := f_powII(2, 3); log("Raise 2 to power 3: ", tmpInt); - if ( tmpInt == 8) { - setverdict(pass); + if ( tmpInt == 8) { + setverdict(pass); } else { setverdict(fail); } } @@ -458,13 +631,13 @@ testcase f_test_powII() runs on Maths_CT testcase f_test_powIF() runs on Maths_CT { log(" ----------- f_powIF ----------- "); - + tmpFloat := f_powIF(2, 3.0); log("Raise 2 to power 3.0: ", tmpFloat); tmpFloat := tmpFloat - 8.0; - if ( tmpFloat * tmpFloat < LIMIT) { - setverdict(pass); + if ( tmpFloat * tmpFloat < LIMIT) { + setverdict(pass); } else { setverdict(fail); } } @@ -472,54 +645,54 @@ testcase f_test_powIF() runs on Maths_CT testcase f_test_powFI() runs on Maths_CT { log(" ----------- f_powFI ----------- "); - + tmpFloat := f_powFI(2.0, 3); log("Raise 2.0 to power 3: ", tmpFloat); tmpFloat := tmpFloat - 8.0; - if ( tmpFloat * tmpFloat < LIMIT) { - setverdict(pass); + if ( tmpFloat * tmpFloat < LIMIT) { + setverdict(pass); } - else { setverdict(fail); } + else { setverdict(fail); } } testcase f_test_powFF_cubicRootOfTwo() runs on Maths_CT { log(" ----------- f_powFF (Cubic root) ----------- "); - + tmpFloat := f_powFF(2.0, 1.0/3.0); log("Raise 2.0 to power 0.3333: ", tmpFloat); tmpFloat := tmpFloat - 1.2599215; - if ( tmpFloat * tmpFloat < LIMIT) { - setverdict(pass); + if ( tmpFloat * tmpFloat < LIMIT) { + setverdict(pass); } - else { setverdict(fail); } + else { setverdict(fail); } } testcase f_test_sqrF() runs on Maths_CT { log(" ----------- f_sqrF ----------- "); - + tmpFloat := f_sqrF(2.0); log("Square of 2.0: ", tmpFloat); tmpFloat := tmpFloat - 4.0; - if ( tmpFloat * tmpFloat < LIMIT) { - setverdict(pass); + if ( tmpFloat * tmpFloat < LIMIT) { + setverdict(pass); } - else { setverdict(fail); } + else { setverdict(fail); } } testcase f_test_sqrI() runs on Maths_CT { log(" ----------- f_sqrI ----------- "); - + tmpInt := f_sqrI(2); log("Square of 2: ", tmpInt); - if ( tmpInt == 4) { - setverdict(pass); + if ( tmpInt == 4) { + setverdict(pass); } else { setverdict(fail); } } @@ -527,13 +700,13 @@ testcase f_test_sqrI() runs on Maths_CT testcase f_test_sqrtF() runs on Maths_CT { log(" ----------- f_sqrtF ----------- "); - + tmpFloat := f_sqrtF(2.0); log("Square root of 2.0: ", tmpFloat); tmpFloat := tmpFloat - 1.4142145; - if ( tmpFloat * tmpFloat < LIMIT) { - setverdict(pass); + if ( tmpFloat * tmpFloat < LIMIT) { + setverdict(pass); } else { setverdict(fail); } } @@ -541,13 +714,13 @@ testcase f_test_sqrtF() runs on Maths_CT testcase f_test_sqrtI() runs on Maths_CT { log(" ----------- f_sqrtI ----------- "); - + tmpFloat := f_sqrtI(2); log("Square root of 2: ", tmpFloat); tmpFloat := tmpFloat - 1.4142145; - if ( tmpFloat * tmpFloat < LIMIT) { - setverdict(pass); + if ( tmpFloat * tmpFloat < LIMIT) { + setverdict(pass); } else { setverdict(fail); } } @@ -555,12 +728,12 @@ testcase f_test_sqrtI() runs on Maths_CT testcase f_test_ceil() runs on Maths_CT { log(" ----------- f_ceil ----------- "); - + tmpInt := f_ceil(3.1); log("ceil of 3.1: ", tmpInt); - if (tmpInt == 4) { - setverdict(pass); + if (tmpInt == 4) { + setverdict(pass); } else { setverdict(fail); } } @@ -568,12 +741,12 @@ testcase f_test_ceil() runs on Maths_CT testcase f_test_floor() runs on Maths_CT { log(" ----------- f_floor ----------- "); - + tmpInt := f_floor(3.1); log("ceil of 3.1: ", tmpInt); - if ( tmpInt == 3) { - setverdict(pass); + if ( tmpInt == 3) { + setverdict(pass); } else { setverdict(fail); } } @@ -592,9 +765,9 @@ testcase f_test_poisson() runs on Maths_CT vl_success:=f_generate_poissonTable(i,vl_poissonTable); log("Poisson table Nr:",i," ,",vl_success); log(vl_poissonTable); - + } - setverdict(pass); + setverdict(pass); } testcase f_test_next_poisson() runs on Maths_CT @@ -611,9 +784,9 @@ testcase f_test_next_poisson() runs on Maths_CT vl_nextValue := f_getNext_poissonValue(i, vl_poissonTable, vl_success); log("Next Poisson value:",vl_nextValue," ,",vl_success); - log(vl_poissonTable); + log(vl_poissonTable); } - setverdict(pass); + setverdict(pass); } @@ -650,7 +823,7 @@ control execute(f_test_acos()); execute(f_test_powFF()); execute(f_test_powII()); - execute(f_test_powIF()); + execute(f_test_powIF()); execute(f_test_powFI()); execute(f_test_powFF_cubicRootOfTwo()); execute(f_test_sqrF()); @@ -659,10 +832,10 @@ control execute(f_test_sqrtI()); execute(f_test_ceil()); execute(f_test_floor()); - + //poisson execute(f_test_poisson()); - execute(f_test_next_poisson()); + execute(f_test_next_poisson()); } } diff --git a/demo/TCCMessageHandling_Example.ttcn b/demo/TCCMessageHandling_Example.ttcn index 6aa78dc..c98c058 100644 --- a/demo/TCCMessageHandling_Example.ttcn +++ b/demo/TCCMessageHandling_Example.ttcn @@ -1,17 +1,16 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2013 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCMessageHandling_Example.ttcn // Description: TCC Useful Functions: Message Handling Functions. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2013-03-28 // Contact: http://ttcn.ericsson.se diff --git a/demo/TCCPermutatedParameters_Example.ttcn b/demo/TCCPermutatedParameters_Example.ttcn index 67190b7..a4e58d5 100644 --- a/demo/TCCPermutatedParameters_Example.ttcn +++ b/demo/TCCPermutatedParameters_Example.ttcn @@ -1,11 +1,13 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// -******************************************************************************/ module TCCPermutatedParameters_Example { diff --git a/demo/TCCRegexp_Example.ttcn b/demo/TCCRegexp_Example.ttcn new file mode 100644 index 0000000..5348575 --- /dev/null +++ b/demo/TCCRegexp_Example.ttcn @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +// +// File: TCCRegexp_Example.ttcn +// Description: TCC Useful Functions: Regular Expression Functions. +// Rev: R30A +// Prodnr: CNL 113 472 +// Contact: http://ttcn.ericsson.se +/////////////////////////////////////////////// +module TCCRegexp_Example +{ +import from TCCRegexp_Functions all; + +type component Test_CT{} + + +testcase tc_1() runs on Test_CT + { + + var charstring vl_subject := "a :1 2\nb:1 2\na :2 3"; + var charstring vl_pattern := "a :(\\d+) (\\d+)"; + + var integer vl_groupno := 0; + var charstring vl_expected := "a :1 2"; + var charstring vl_result := f_pcre_regexp(vl_subject, vl_pattern, vl_groupno); + log(vl_result); + if(vl_result == vl_expected) {setverdict(pass)} else {setverdict(fail)} + + var charstring_list vl_expected2 := {"a :1 2", "1", "2"}; + var charstring_list vl_result2 := f_pcre_regexp_list(vl_subject, vl_pattern); + log(vl_result2) + if(vl_result2 == vl_expected2) {setverdict(pass)} else {setverdict(fail)} + + var t_list_of_charstring_list vl_expected3 := {{"a :1 2", "1", "2"},{"a :2 3", "2", "3"}}; + var t_list_of_charstring_list vl_result3 := f_pcre_regexp_list_all_matches(vl_subject, vl_pattern); + log(vl_result3) + if(vl_result3 == vl_expected3) {setverdict(pass)} else {setverdict(fail)} + } +control +{ + execute(tc_1()) +} + + +} diff --git a/demo/TCCTemplate_Example.ttcn b/demo/TCCTemplate_Example.ttcn index 0c4570c..44c9c45 100644 --- a/demo/TCCTemplate_Example.ttcn +++ b/demo/TCCTemplate_Example.ttcn @@ -1,16 +1,16 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCTemplate_Example.ttcn // Description: TCC Useful Functions: Template Functions. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2007-12-20 // Contact: http://ttcn.ericsson.se diff --git a/demo/TCCTitanMetadata_Example.ttcn b/demo/TCCTitanMetadata_Example.ttcn index c7265d3..91f4efd 100644 --- a/demo/TCCTitanMetadata_Example.ttcn +++ b/demo/TCCTitanMetadata_Example.ttcn @@ -1,16 +1,16 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCTitanMetadata_Example.ttcn // Description: TCC Useful Functions: Titan Metadata Functions. -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2007-11-14 // Contact: http://ttcn.ericsson.se diff --git a/demo/TCCXPathSupport_Example.ttcn b/demo/TCCXPathSupport_Example.ttcn index d3bd561..3b8f110 100644 --- a/demo/TCCXPathSupport_Example.ttcn +++ b/demo/TCCXPathSupport_Example.ttcn @@ -1,16 +1,16 @@ -/****************************************************************************** -* Copyright (c) 2004, 2015 Ericsson AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v1.0 -* which accompanies this distribution, and is available at -* http://www.eclipse.org/legal/epl-v10.html - -******************************************************************************/ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCXPathSupport_Example.ttcn // Description: TCC Useful Functions: XPath Support Functions -// Rev: R22B +// Rev: R30A // Prodnr: CNL 113 472 // Updated: 2008-09-04 // Contact: http://ttcn.ericsson.se diff --git a/doc/TCCUsefulFunctions_CNL113472_1551.doc b/doc/TCCUsefulFunctions_CNL113472_1551.doc index b82cc3a68ff785e12d9836e3b820fdf3cc504863..1ae7690e94907c6ac2e85a3aa75789ffb477a29c 100644 GIT binary patch delta 89522 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 delta 81590 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 DMPWAF diff --git a/doc/TCCUsefulFunctions_CNL113472_PRI.doc b/doc/TCCUsefulFunctions_CNL113472_PRI.doc index a56962994c8b617bb5afdeeeb252a68cce4254b9..d90970b743c58ed176fc9063cc44ae4fa12e7614 100644 GIT binary patch literal 156160 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 J|4&PS{{uHcK}`Sv literal 143360 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 YzNd2C)1Urqx?!MF+TObVX({mk00)VRT>t<8 diff --git a/doc/apidoc/Data/ClassHierarchy.nd b/doc/apidoc/Data/ClassHierarchy.nd old mode 100644 new mode 100755 diff --git a/doc/apidoc/Data/ConfigFileInfo.nd b/doc/apidoc/Data/ConfigFileInfo.nd old mode 100644 new mode 100755 diff --git a/doc/apidoc/Data/FileInfo.nd b/doc/apidoc/Data/FileInfo.nd old mode 100644 new mode 100755 diff --git a/doc/apidoc/Data/ImageFileInfo.nd b/doc/apidoc/Data/ImageFileInfo.nd old mode 100644 new mode 100755 diff --git a/doc/apidoc/Data/ImageReferenceTable.nd b/doc/apidoc/Data/ImageReferenceTable.nd old mode 100644 new mode 100755 diff --git a/doc/apidoc/Data/IndexInfo.nd b/doc/apidoc/Data/IndexInfo.nd old mode 100644 new mode 100755 diff --git a/doc/apidoc/Data/PreviousMenuState.nd b/doc/apidoc/Data/PreviousMenuState.nd old mode 100644 new mode 100755 diff --git a/doc/apidoc/Data/PreviousSettings.nd b/doc/apidoc/Data/PreviousSettings.nd old mode 100644 new mode 100755 diff --git a/doc/apidoc/Data/SymbolTable.nd b/doc/apidoc/Data/SymbolTable.nd old mode 100644 new mode 100755 diff --git a/doc/apidoc/Menu.txt b/doc/apidoc/Menu.txt old mode 100644 new mode 100755 diff --git a/doc/apidoc/Menu.txt~ b/doc/apidoc/Menu.txt~ deleted file mode 100644 index f53b1c2..0000000 --- a/doc/apidoc/Menu.txt~ +++ /dev/null @@ -1,165 +0,0 @@ -Format: 1.4 - - -Title: TCCUsefulFunctions -SubTitle: R12A02 - -Footer: Copyright 2012 Test Competence Center<br/><a href="http://ttcn.ericsson.se/">http://ttcn.ericsson.se</a> - -# You can add a timestamp to your documentation like one of these: -# Timestamp: Generated on month day, year -# Timestamp: Updated mm/dd/yyyy -# Timestamp: Last updated mon day -# -# m - One or two digit month. January is "1" -# mm - Always two digit month. January is "01" -# mon - Short month word. January is "Jan" -# month - Long month word. January is "January" -# d - One or two digit day. 1 is "1" -# dd - Always two digit day. 1 is "01" -# day - Day with letter extension. 1 is "1st" -# yy - Two digit year. 2006 is "06" -# yyyy - Four digit year. 2006 is "2006" -# year - Four digit year. 2006 is "2006" - - -# -------------------------------------------------------------------------- -# -# Cut and paste the lines below to change the order in which your files -# appear on the menu. Don't worry about adding or removing files, Natural -# Docs will take care of that. -# -# You can further organize the menu by grouping the entries. Add a -# "Group: [name] {" line to start a group, and add a "}" to end it. -# -# You can add text and web links to the menu by adding "Text: [text]" and -# "Link: [name] ([URL])" lines, respectively. -# -# The formatting and comments are auto-generated, so don't worry about -# neatness when editing the file. Natural Docs will clean it up the next -# time it is run. When working with groups, just deal with the braces and -# forget about the indentation and comments. -# -# -------------------------------------------------------------------------- - - -Group: Aka-algorythm { - - File: aka_algorythm_set.h (aka_algorythm_set.h) - } # Group: Aka-algorythm - -Group: Assertion { - - File: f__assert (TCCAssertion.cc) - File: TCCAssertion_Functions (TCCAssertion_Functions.ttcn) - } # Group: Assertion - -Group: Conversion { - - File: TCCConversion.cc (TCCConversion.cc) - File: TCCConversion_Functions (TCCConversion_Functions.ttcn) - } # Group: Conversion - -Group: Date-Time { - - File: TCCDateTime.cc (TCCDateTime.cc) - File: TCCDateTime_Functions (TCCDateTime_Functions.ttcn) - } # Group: Date-Time - -Group: Digcalc { - - File: digcalc.h (digcalc.h) - } # Group: Digcalc - -Group: Encoding { - - File: TCCEncoding.cc (TCCEncoding.cc) - File: TCCEncoding_Functions (TCCEncoding_Functions.ttcn) - } # Group: Encoding - -Group: Env { - - File: TCCEnv.cc (TCCEnv.cc) - File: TCCEnv_Functions (TCCEnv_Functions.ttcn) - } # Group: Env - -Group: File { - - File: TCCFileIO.cc (TCCFileIO.cc) - File: TCCFileIO_Functions (TCCFileIO_Functions.ttcn) - File: TCCFileSystem_Functions (TCCFileSystem_Functions.ttcn) - } # Group: File - -Group: IP { - - File: TCCIPsec_Definitions.ttcn (TCCIPsec_Definitions.ttcn) - File: TCCIPsec_Functions (TCCIPsec_Functions.ttcn) - } # Group: IP - -Group: Interface { - - File: TCCInterface.cc (TCCInterface.cc) - File: TCCInterface_Functions (TCCInterface_Functions.ttcn) - } # Group: Interface - -Group: Math { - - File: TCCMaths.cc (TCCMaths.cc) - File: TCCMaths_Functions (TCCMaths_Functions.ttcn) - File: TCCMaths_GenericTypes (TCCMaths_GenericTypes.ttcn) - } # Group: Math - -Group: Message-Handling { - - File: TCCMessageHandling_Functions (TCCMessageHandling_Functions.ttcn) - } # Group: Message-Handling - -Group: Regexp { - - File: Regexp_Functions (TCCRegexp_Functions.ttcn) - } # Group: Regexp - -Group: Security { - - File: TCCSecurity.cc (TCCSecurity.cc) - File: TCCSecurity_Functions (TCCSecurity_Functions.ttcn) - } # Group: Security - -Group: System { - - File: f_SYS_getpid (TCCSystem.cc) - File: f_SYS_getpid (TCCSystem_Functions.ttcn) - } # Group: System - -Group: Template { - - File: TCCTemplate_Functions (TCCTemplate_Functions.ttcn) - } # Group: Template - -Group: Titan-Metadata { - - File: f__compilationTime (TCCTitanMetadata.cc) - File: TCCTitanMetadata_Functions (TCCTitanMetadata_Functions.ttcn) - } # Group: Titan-Metadata - -Group: XPath-Support { - - File: TCCXPathSupport_Functions (TCCXPathSupport_Functions.ttcn) - File: XPathQuery (TCCXPathSupport.cc) - } # Group: XPath-Support - -Group: Zuc { - - File: zuc.h (zuc.h) - } # Group: Zuc - -Group: Index { - - Index: Everything - Constant Index: Constants - File Index: Files - Function Index: Functions - Type Index: Types - Variable Index: Variables - } # Group: Index - diff --git a/doc/apidoc/html/index.html~ b/doc/apidoc/html/index.html~ deleted file mode 100644 index 95dcc7c..0000000 --- a/doc/apidoc/html/index.html~ +++ /dev/null @@ -1,21 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-html40/frameset.dtd"> -<html> -<head> -<title>TCCUsefulFunctions</title></head> - -<!-- Copyright (c) 2015 Ericsson --> - -<frameset cols="250,*"> - <frame name=Menu src="menu.html"> - <frame name=Content src="files/TCCUsefulFunctions.html"> -</frameset> - -<noframes> -This documentation was designed for use with frames. However, you can still use it by <a href="menu.html">starting from the menu page</a>. -<script language=JavaScript> -<!-- -location.href="menu.html"; -// --> -</script> -</noframes> -</html> diff --git a/doc/apidoc/html/javascript/main.js b/doc/apidoc/html/javascript/main.js old mode 100644 new mode 100755 diff --git a/doc/apidoc/html/javascript/searchdata.js b/doc/apidoc/html/javascript/searchdata.js old mode 100644 new mode 100755 diff --git a/doc/apidoc/html/menu.html~ b/doc/apidoc/html/menu.html~ deleted file mode 100644 index f637c1d..0000000 --- a/doc/apidoc/html/menu.html~ +++ /dev/null @@ -1,254 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> - -<html> -<head> -<title>Menu - TCCUsefulFunctions</title> -<base target="Content"> -<link rel="stylesheet" type="text/css" href="styles/main.css"> -<script language=JavaScript src="javascript/main.js"></script> -<script language=JavaScript src="javascript/searchdata.js"></script></head> -<body class="FramedMenuPage" onLoad="NDOnLoad()"> -<script language=JavaScript> -<!-- -if (browserType) {document.write("<div class=" + browserType + ">");if (browserVer) {document.write("<div class=" + browserVer + ">"); }}// --></script> - -<!-- Generated by Natural Docs, version 1.4 --> -<!-- http://www.naturaldocs.org --> - -<!-- saved from url=(0026)http://www.naturaldocs.org --> - - - - -<div id=Menu> -<div class=MTitle>TCCUsefulFunctions<div class=MSubTitle>R12A02</div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent1')" target="_self">Aka-algorythm</a> -<div class=MGroupContent id=MGroupContent1> -<div class=MEntry> -<div class=MFile> -<a href="files/aka_algorythm_set-h.html">aka_algorythm_set.h</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent2')" target="_self">Assertion</a> -<div class=MGroupContent id=MGroupContent2> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCAssertion-cc.html">f__assert</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCAssertion_Functions-ttcn.html">TCCAssertion_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent3')" target="_self">Conversion</a> -<div class=MGroupContent id=MGroupContent3> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCConversion-cc.html">TCCConversion.cc</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCConversion_Functions-ttcn.html">TCCConversion_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent4')" target="_self">Date-Time</a> -<div class=MGroupContent id=MGroupContent4> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCDateTime-cc.html">TCCDateTime.cc</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCDateTime_Functions-ttcn.html">TCCDateTime_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent5')" target="_self">Digcalc</a> -<div class=MGroupContent id=MGroupContent5> -<div class=MEntry> -<div class=MFile> -<a href="files/digcalc-h.html">digcalc.h</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent6')" target="_self">Encoding</a> -<div class=MGroupContent id=MGroupContent6> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCEncoding-cc.html">TCCEncoding.cc</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCEncoding_Functions-ttcn.html">TCCEncoding_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent7')" target="_self">Env</a> -<div class=MGroupContent id=MGroupContent7> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCEnv-cc.html">TCCEnv.cc</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCEnv_Functions-ttcn.html">TCCEnv_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent8')" target="_self">File</a> -<div class=MGroupContent id=MGroupContent8> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCFileIO-cc.html">TCCFileIO.cc</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCFileIO_Functions-ttcn.html">TCCFileIO_Functions</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCFileSystem_Functions-ttcn.html">TCCFileSystem_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent9')" target="_self">IP</a> -<div class=MGroupContent id=MGroupContent9> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCIPsec_Definitions-ttcn.html">TCCIPsec_Definitions.ttcn</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCIPsec_Functions-ttcn.html">TCCIPsec_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent10')" target="_self">Interface</a> -<div class=MGroupContent id=MGroupContent10> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCInterface-cc.html">TCCInterface.cc</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCInterface_Functions-ttcn.html">TCCInterface_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent11')" target="_self">Math</a> -<div class=MGroupContent id=MGroupContent11> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCMaths-cc.html">TCCMaths.cc</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCMaths_Functions-ttcn.html">TCCMaths_Functions</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCMaths_GenericTypes-ttcn.html">TCCMaths_GenericTypes</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent12')" target="_self">Message-Handling</a> -<div class=MGroupContent id=MGroupContent12> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCMessageHandling_Functions-ttcn.html">TCCMessageHandling_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent13')" target="_self">Regexp</a> -<div class=MGroupContent id=MGroupContent13> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCRegexp_Functions-ttcn.html">Regexp_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent14')" target="_self">Security</a> -<div class=MGroupContent id=MGroupContent14> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCSecurity-cc.html">TCCSecurity.cc</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCSecurity_Functions-ttcn.html">TCCSecurity_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent15')" target="_self">System</a> -<div class=MGroupContent id=MGroupContent15> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCSystem-cc.html">f_SYS_getpid</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCSystem_Functions-ttcn.html">f_SYS_getpid</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent16')" target="_self">Template</a> -<div class=MGroupContent id=MGroupContent16> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCTemplate_Functions-ttcn.html">TCCTemplate_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent17')" target="_self">Titan-Metadata</a> -<div class=MGroupContent id=MGroupContent17> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCTitanMetadata-cc.html">f__compilationTime</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCTitanMetadata_Functions-ttcn.html">TCCTitanMetadata_Functions</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent18')" target="_self">XPath-Support</a> -<div class=MGroupContent id=MGroupContent18> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCXPathSupport_Functions-ttcn.html">TCCXPathSupport_Functions</a></div></div> -<div class=MEntry> -<div class=MFile> -<a href="files/TCCXPathSupport-cc.html">XPathQuery</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent19')" target="_self">Zuc</a> -<div class=MGroupContent id=MGroupContent19> -<div class=MEntry> -<div class=MFile> -<a href="files/zuc-h.html">zuc.h</a></div></div></div></div></div> -<div class=MEntry> -<div class=MGroup> -<a href="javascript:ToggleMenu('MGroupContent20')" target="_self">Index</a> -<div class=MGroupContent id=MGroupContent20> -<div class=MEntry> -<div class=MIndex> -<a href="index/General.html">Everything</a></div></div> -<div class=MEntry> -<div class=MIndex> -<a href="index/Constants.html">Constants</a></div></div> -<div class=MEntry> -<div class=MIndex> -<a href="index/Files.html">Files</a></div></div> -<div class=MEntry> -<div class=MIndex> -<a href="index/Functions.html">Functions</a></div></div> -<div class=MEntry> -<div class=MIndex> -<a href="index/Types.html">Types</a></div></div> -<div class=MEntry> -<div class=MIndex> -<a href="index/Variables.html">Variables</a></div></div></div></div></div> -<script type="text/javascript"> -<!-- -var searchPanel = new SearchPanel("searchPanel", "FramedHTML", "search"); ---></script> -<div id=MSearchPanel class=MSearchPanelInactive> -<input type=text id=MSearchField value=Search onFocus="searchPanel.OnSearchFieldFocus(true)" onBlur="searchPanel.OnSearchFieldFocus(false)" onKeyUp="searchPanel.OnSearchFieldChange()"> -<select id=MSearchType onFocus="searchPanel.OnSearchTypeFocus(true)" onBlur="searchPanel.OnSearchTypeFocus(false)" onChange="searchPanel.OnSearchTypeChange()"> -<option id=MSearchEverything selected value="General">Everything</option> -<option value="Constants">Constants</option> -<option value="Files">Files</option> -<option value="Functions">Functions</option> -<option value="Types">Types</option> -<option value="Variables">Variables</option></select></div> -<script language=JavaScript> -<!-- -HideAllBut([], 21);// --></script></div> -<!--Menu--> - - -<div id=Footer> -<p>Copyright 2012 Test Competence Center<br/> -<a href="http://ttcn.ericsson.se/">http://ttcn.ericsson.se</a></p> -<p> -<a href="http://www.naturaldocs.org">Generated by Natural Docs</a></p></div> -<!--Footer--> - - -<script language=JavaScript> -<!-- -if (browserType) {if (browserVer) {document.write("</div>"); }document.write("</div>");}// --></script></body></html> \ No newline at end of file diff --git a/doc/apidoc/html/styles/1.css b/doc/apidoc/html/styles/1.css old mode 100644 new mode 100755 diff --git a/doc/apidoc/html/styles/2.css b/doc/apidoc/html/styles/2.css old mode 100644 new mode 100755 diff --git a/doc/apidoc/html/styles/main.css b/doc/apidoc/html/styles/main.css old mode 100644 new mode 100755 diff --git a/src/TCCAssertion.cc b/src/TCCAssertion.cc index 41b38e3..03d0d96 100644 --- a/src/TCCAssertion.cc +++ b/src/TCCAssertion.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2007 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCAssertion.cc // Description: TCC Useful Functions: Assert Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2007-11-12 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCAssertion_Functions.ttcn b/src/TCCAssertion_Functions.ttcn index 28bb7ad..526c950 100644 --- a/src/TCCAssertion_Functions.ttcn +++ b/src/TCCAssertion_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2007 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCAssertion_Functions.ttcn // Description: TCC Useful Functions: Assert Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2007-11-12 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCConversion.cc b/src/TCCConversion.cc index 668203a..6d5f58a 100644 --- a/src/TCCConversion.cc +++ b/src/TCCConversion.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2013 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCConversion.cc // Description: TCC Useful Functions: Conversion Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2013-04-15 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCConversion_Functions.ttcn b/src/TCCConversion_Functions.ttcn index c828ac6..b4df9b6 100644 --- a/src/TCCConversion_Functions.ttcn +++ b/src/TCCConversion_Functions.ttcn @@ -1,19 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2016 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCConversion_Functions.ttcn // Description: TCC Useful Functions: Conversion Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// @@ -971,5 +969,5 @@ return boolean }//end of module with { -extension "version R25A"} +extension "version R30A"} diff --git a/src/TCCDateTime.cc b/src/TCCDateTime.cc index 68a73a1..553426f 100644 --- a/src/TCCDateTime.cc +++ b/src/TCCDateTime.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2011 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCDateTime.cc // Description: TCC Useful Functions: DateTime Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2011-06-29 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCDateTime_Functions.ttcn b/src/TCCDateTime_Functions.ttcn index 023c0f0..2be3f65 100644 --- a/src/TCCDateTime_Functions.ttcn +++ b/src/TCCDateTime_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2007 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCDateTime_Functions.ttcn // Description: TCC Useful Functions: DateTime Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2011-06-29 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCEncoding.cc b/src/TCCEncoding.cc index 9df864a..00f4d07 100644 --- a/src/TCCEncoding.cc +++ b/src/TCCEncoding.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2012 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCEncoding.cc // Description: TCC Useful Functions: Message Encoding Functions. -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2012-06-28 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCEncoding_Functions.ttcn b/src/TCCEncoding_Functions.ttcn index 603ceb1..b9f721a 100644 --- a/src/TCCEncoding_Functions.ttcn +++ b/src/TCCEncoding_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2013 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCEncoding_Functions.ttcn // Description: TCC Useful Functions: Message Encoding Functions. -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2013-08-05 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// @@ -733,4 +730,4 @@ public function f_enc_TBCD_hex(in hexstring pl_hex) return octetstring return vl_oct; } -} with {extension "version R25A"} +} with {extension "version R30A"} diff --git a/src/TCCEnv.cc b/src/TCCEnv.cc index d35c2a3..de7bb1e 100644 --- a/src/TCCEnv.cc +++ b/src/TCCEnv.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2008 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCEnv.cc // Description: TCC Useful Functions: Environment Handling Functions. -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2008-01-18 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCEnv_Functions.ttcn b/src/TCCEnv_Functions.ttcn index a1e45e2..57d05c8 100644 --- a/src/TCCEnv_Functions.ttcn +++ b/src/TCCEnv_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2008 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCEnv_Functions.ttcn // Description: TCC Useful Functions: Environment Handling Functions. -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2008-01-18 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCFileIO.cc b/src/TCCFileIO.cc index 09b0b21..91be44a 100644 --- a/src/TCCFileIO.cc +++ b/src/TCCFileIO.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2009 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCFileIO.cc // Description: TCC Useful Functions: FileIO Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2009-04-09 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// @@ -31,6 +28,7 @@ #include <map> #include <string> #include <sstream> +#include <dirent.h> #define BUF_SIZE 512 @@ -1098,6 +1096,35 @@ BOOLEAN f__FIO__rmdir(const CHARSTRING& pl__dir__name) return TRUE; } +/////////////////////////////////////////////////////////////////////////////// +// Function: f__FIO__remove +// +// Purpose: +// Removes folder or a directory +// +// Parameters: +// pl_file_name - *in* *charstring* - name of the folder/directory to remove +// +// Return Value: +// boolean - indicate the successful or unsuccessful target removal +// +// Errors: +// In the case of unsuccessful operation the cause of the error can be +// queried by the f_FIO_get_error_code, f_FIO_get_error_string functions +// +/////////////////////////////////////////////////////////////////////////////// +BOOLEAN f__FIO__remove(const CHARSTRING& pl__file__name) +{ + if(remove((const char *)(pl__file__name))) + { + f__FIO__realize__error ("f__FIO__remove", + "Cannot remove ", __FILE__, __LINE__); + return FALSE; + } + else + return TRUE; +} + /////////////////////////////////////////////////////////////////////////////// // Function: f_FIO_fileOrDirExists // @@ -1335,4 +1362,33 @@ BOOLEAN f__FIO__chmod(const CHARSTRING& p__name, return TRUE; } +INTEGER f__FIO__fileSize(const CHARSTRING& filename ) { + struct stat buffer ; + if(stat( (const char *)filename, &buffer )==0) { + return INTEGER(buffer.st_size); + } + else{return INTEGER (-1);} +} + +BOOLEAN f__FIO__fileList(const CHARSTRING& dirname, FileList& filelist) { + struct dirent *pent; + DIR *pdir; + pdir=opendir((const char *)dirname); + if(!pdir) { + return FALSE; + } + else{ + errno=0; + int i=0; + while((pent=readdir(pdir))) + { + filelist[i] = (pent->d_name); + i = i+1; + } + closedir(pdir); + if (errno){return FALSE;} + return TRUE; + } +} + } diff --git a/src/TCCFileIO_Functions.ttcn b/src/TCCFileIO_Functions.ttcn index f78878b..94b5bc6 100644 --- a/src/TCCFileIO_Functions.ttcn +++ b/src/TCCFileIO_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2009 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCFileIO_Functions.ttcn // Description: TCC Useful Functions: FileIO Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2009-04-09 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// @@ -412,6 +409,25 @@ external function f_FIO_chdir (in charstring pl_name) return boolean; /////////////////////////////////////////////////////////////////////////////// external function f_FIO_mkdir (in charstring p_dir_name) return boolean; +/////////////////////////////////////////////////////////////////////////////// +// Function: f_FIO_remove +// +// Purpose: +// Removes folder or a directory +// +// Parameters: +// pl_file_name - *in* *charstring* - name of the folder/directory to remove +// +// Return Value: +// boolean - indicate the successful or unsuccessful target removal +// +// Errors: +// In the case of unsuccessful operation the cause of the error can be +// queried by the f_FIO_get_error_code, f_FIO_get_error_string functions +// +/////////////////////////////////////////////////////////////////////////////// +external function f_FIO_remove (in charstring pl_file_name) return boolean; + /////////////////////////////////////////////////////////////////////////////// // Function: f_FIO_rmdir // @@ -548,4 +564,49 @@ external function f_FIO_stat (in charstring p_name, external function f_FIO_chmod (in charstring p_name, in FIO_permissions p_permissions) return boolean; +/////////////////////////////////////////////////////////////////////////////// +// Function: f_FIO_fileSize +// +// Purpose: +// Query the size of the file. +// +// Parameters: +// p_name - *in* *charstring* - name of the file to check +// +// Return Value: +// integer - the size of the file in bytes, or -1 on error +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function f_FIO_fileSize (in charstring p_name) return integer; + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_FIO_fileList +// +// Purpose: +// Query the contents of a directory. +// +// Parameters: +// p_name - *in* *charstring* - name of the directory to check +// p_files - *inout* *FileList* - the contents of the directory +// +// Return Value: +// boolean - indicate sucessfull execution +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +type record of charstring FileList; +external function f_FIO_fileList (in charstring p_name, + inout FileList p_files) return boolean; + } diff --git a/src/TCCFileSystem.cc b/src/TCCFileSystem.cc index 4cc851a..eae9578 100644 --- a/src/TCCFileSystem.cc +++ b/src/TCCFileSystem.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2011 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCFileSystem.cc // Description: TCC Useful Functions: FileSystem Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2011-07-14 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCFileSystem_Functions.ttcn b/src/TCCFileSystem_Functions.ttcn index 62b96ba..5606ccf 100644 --- a/src/TCCFileSystem_Functions.ttcn +++ b/src/TCCFileSystem_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2011 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCC_FileSystem_Functions.ttcn // Description: TCC Useful Functions: FileSystem Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2011-07-14 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCIPsec.cc b/src/TCCIPsec.cc index 4dc4224..06dcc78 100644 --- a/src/TCCIPsec.cc +++ b/src/TCCIPsec.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2016 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCIPsec.cc // Description: TCC Useful Functions: IPsec Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2012-10-31 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCIPsec_Definitions.ttcn b/src/TCCIPsec_Definitions.ttcn index 7d2fed5..49e2d4d 100644 --- a/src/TCCIPsec_Definitions.ttcn +++ b/src/TCCIPsec_Definitions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2012 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCIPsec_Definitions.ttcn // Description: TCC Useful Functions: Definitions for IPsec functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2012-10-31 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCIPsec_Functions.ttcn b/src/TCCIPsec_Functions.ttcn index 5300418..f831e11 100644 --- a/src/TCCIPsec_Functions.ttcn +++ b/src/TCCIPsec_Functions.ttcn @@ -1,19 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2016 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCIPsec_Functions.ttcn // Description: TCC Useful Functions: IPsec Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCIPsec_XFRM.cc b/src/TCCIPsec_XFRM.cc new file mode 100644 index 0000000..3c8ad7f --- /dev/null +++ b/src/TCCIPsec_XFRM.cc @@ -0,0 +1,358 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +// +// File: TCCIPsec_XFRM.cc +// Description: TCC Useful Functions: IPsec XFRM Functions +// Rev: R30A +// Prodnr: CNL 113 472 +// +/////////////////////////////////////////////////////////////////////////////// +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <asm/types.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <unistd.h> +#include <arpa/inet.h> +#include <errno.h> +#include <time.h> +#include <signal.h> + +#ifdef LINUX + #include <linux/netlink.h> +#else + #include <net/netlink.h> +#endif + +#include "TCCIPsec_XFRM_Definitions.hh" +#include "TCCIPsec_XFRM.hh" +#include "Logger.hh" + +class Message{ +public: + void* memory; +public: + Message(int size){ + memory = Malloc(size); + } + + ~Message(){ + Free(memory); //so no one forgets to free the allocated memory :) + } +}; //end of class Message + +namespace TCCIPsec__XFRM__Definitions { + +XFRM__Result send(int fd, void* msg, int len, unsigned long* spi) { + struct msghdr smsg; + struct iovec siov; + struct sockaddr_nl dest; + char recvbuf[4096]; + struct msghdr rmsg; + struct iovec riov; + struct sockaddr_nl from; + struct nlmsghdr* hdr; + int rlen; + + memset(&dest,0,sizeof(dest)); + dest.nl_family = AF_NETLINK; + smsg.msg_name = (void*)&dest; + smsg.msg_namelen = sizeof(dest); + smsg.msg_iov = &siov; + smsg.msg_iovlen = 1; + smsg.msg_control = NULL; + smsg.msg_controllen = 0; + smsg.msg_flags = 0; + + siov.iov_base = msg; + siov.iov_len = len; + + //Sending message to the kernel + if(sendmsg(fd,&smsg,0) == -1){ + close(fd); + return XFRM__Result(-1,"TCCIPsec XFRM: Netlink socket send failed."); + } + + TTCN_Logger::log( TTCN_DEBUG,"###### Netlink socket sent."); + //Initializing reciever + riov.iov_base = recvbuf; + riov.iov_len = 4096; + rmsg.msg_name = &from; + rmsg.msg_namelen = sizeof(from); + rmsg.msg_iov = &riov; + rmsg.msg_iovlen = 1; + rmsg.msg_control = NULL; + rmsg.msg_controllen = 0; + rmsg.msg_flags = 0; + + TTCN_Logger::log( TTCN_DEBUG,"###### Receiving results from the kernel:"); + rlen = recvmsg(fd,&rmsg,0); + if(rlen == -1) { + close(fd); + return XFRM__Result(-1,"TCCIPsec XFRM: Error in receiving message from the kernel!"); + }; + + //Processing response + //Message Format: + // <--- nlmsg_total_size(payload) ---> + // <-- nlmsg_msg_size(payload) -> + //+----------+- - -+-------------+- - -+-------- - - + //| nlmsghdr | Pad | Payload | Pad | nlmsghdr + //+----------+- - -+-------------+- - -+-------- - - + //nlmsg_data(nlh)---^ ^ + //nlmsg_next(nlh)-----------------------+ + for(hdr = (struct nlmsghdr*)recvbuf; NLMSG_OK(hdr,(unsigned)rlen); hdr = NLMSG_NEXT(hdr,rlen)){ + if(hdr -> nlmsg_type == NLMSG_ERROR){ + struct nlmsgerr* answer = (struct nlmsgerr*)NLMSG_DATA(hdr); + if(answer -> error == 0){ + TTCN_Logger::log( TTCN_DEBUG,"Operation was successful!"); + } else { + close(fd); + return XFRM__Result(-1,strerror(-answer->error)); + }; + } else if(hdr -> nlmsg_type == 16){ + //Allocate SPI answer + struct xfrm_userspi_info* data = (struct xfrm_userspi_info*)NLMSG_DATA(hdr); + *spi = (unsigned long)htonl(data->info.id.spi); + } else { + close(fd); + return XFRM__Result(-1, "Unexpected message from kernel! Message type: "+(char)hdr->nlmsg_type); + }; + }; + close(fd); + return XFRM__Result(0,"TCCIPsec XFRM: Success!"); +} + +XFRM__Result create_socket(void* memo, unsigned int size, unsigned long* spi){ + int xfd; + struct sockaddr_nl address; + + //Creating Netlink socket + xfd = socket(AF_NETLINK,SOCK_DGRAM,NETLINK_XFRM); + if(xfd == -1){ + return XFRM__Result(-1,"TCCIPsec XFRM: Failed!"); + }; + TTCN_Logger::log( TTCN_DEBUG,"###### Netlink socket created."); + + memset(&address,0,sizeof(address)); + address.nl_family = AF_NETLINK; + if(bind(xfd,(struct sockaddr*)&address,sizeof(address)) == -1){ + close(xfd); + return XFRM__Result(-1,"TCCIPsec XFRM: Failed to bind soscket"); + }; + + TTCN_Logger::log( TTCN_DEBUG,"###### Sending socket to the kernel:"); + return send(xfd, memo, size, spi); +} + +void f_set_MessageHeader(void* memo, const int type, const unsigned int length){ + struct nlmsghdr* hdr; + hdr = (struct nlmsghdr*)memo; + + //Setting the message headers + hdr->nlmsg_len = NLMSG_LENGTH(length); + hdr->nlmsg_type = type; + hdr->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; + hdr->nlmsg_seq = 1; + hdr->nlmsg_pid = 0; + return; +} + +XFRM__Result f__XFRM__add__sa(const SAAddInfo& sa_info){ + unsigned long spi = 0; + unsigned int enc_key_len = 0; + unsigned int auth_key_len = 0; + unsigned int payload_len; + int size; + + TTCN_Logger::log( TTCN_DEBUG,"###### Adding new SAs to the database:"); + payload_len = NLA_ALIGN(sizeof(struct xfrm_usersa_info)); + //Calculating length of the encryption key + if(sa_info.ipsec__algos().enc().ispresent()) { + if(sa_info.ipsec__algos().enc()().key().get_selection() == IPSecKey::ALT_text){ + enc_key_len = sa_info.ipsec__algos().enc()().key().text().lengthof(); + } else { + enc_key_len = sa_info.ipsec__algos().enc()().key().hex().lengthof()/2; + }; + payload_len += NLA_HDRLEN+NLA_ALIGN(sizeof(struct xfrm_algo)+enc_key_len); + }; + + //Calculating length of the authentication key + if(sa_info.ipsec__algos().auth().ispresent()) { + if(sa_info.ipsec__algos().auth()().key().get_selection() == IPSecKey::ALT_text)auth_key_len = sa_info.ipsec__algos().auth()().key().text().lengthof(); + else auth_key_len = sa_info.ipsec__algos().auth()().key().hex().lengthof()/2; + payload_len += NLA_HDRLEN+NLA_ALIGN(sizeof(struct xfrm_algo)+auth_key_len); + }; + if(sa_info.nat__t().ispresent()) { + payload_len += NLA_HDRLEN+NLA_ALIGN(sizeof(struct xfrm_encap_tmpl)); + }; + + size = NLMSG_SPACE(payload_len); + Message msg = Message(size); + int message_type = XFRM_MSG_NEWSA; + if(sa_info.update().ispresent()){ + if(sa_info.update()())message_type = XFRM_MSG_UPDSA; + }; + + f_set_MessageHeader(msg.memory,message_type,payload_len); + f_set_MessageBody_for_addSA(msg.memory, sa_info, enc_key_len, auth_key_len); + + return create_socket(msg.memory, size, &spi); +}; + + +XFRM__Result f__XFRM__delete__sa(const SADelInfo& sa_info){ + unsigned long spi = 0; + unsigned int payload_len; + int size; + + TTCN_Logger::log( TTCN_DEBUG,"###### Deleting SA from the database:"); + payload_len = NLA_ALIGN(sizeof(struct xfrm_usersa_id)) + +NLA_HDRLEN+NLA_ALIGN(sizeof(xfrm_address_t)); + + size = NLMSG_SPACE(payload_len); + Message msg = Message(size); + f_set_MessageHeader(msg.memory,XFRM_MSG_DELSA,payload_len); + f_set_MessageBody_for_deleteSA(msg.memory, sa_info); + + return create_socket(msg.memory, size, &spi); +}; + +XFRM__Result f__XFRM__flush__sa(){ + unsigned long spi = 0; + const unsigned int payload_len = NLA_ALIGN(sizeof(struct xfrm_usersa_flush)); + int size = NLMSG_SPACE(payload_len); + struct xfrm_usersa_flush* sa; + Message msg = Message(size); + + TTCN_Logger::log( TTCN_DEBUG,"###### Flushing SA database"); + f_set_MessageHeader(msg.memory,XFRM_MSG_FLUSHSA,payload_len); + + sa = (struct xfrm_usersa_flush*)NLMSG_DATA(msg.memory); + memset(sa,0,sizeof(struct xfrm_usersa_flush)); + + return create_socket(msg.memory, size, &spi); +}; + +XFRM__Result f__XFRM__add__policy(const SPAddInfo& pol_info){ + unsigned long spi = 0; + unsigned int payload_len; + int size; + int numberOfTmpls = pol_info.tmpl().size_of(); + + TTCN_Logger::log( TTCN_DEBUG,"###### Adding new policies to the database:"); + payload_len = NLA_ALIGN(sizeof(struct xfrm_userpolicy_info)) + +(NLA_HDRLEN+NLA_ALIGN(sizeof(struct xfrm_user_tmpl)))*numberOfTmpls; + size = NLMSG_SPACE(payload_len); + + Message msg = Message(size); + int message_type = XFRM_MSG_NEWPOLICY; + if(pol_info.update().ispresent()){ + if(pol_info.update()())message_type = XFRM_MSG_UPDPOLICY; + }; + + f_set_MessageHeader(msg.memory,message_type,payload_len); + f_set_SP_add_info(msg.memory, pol_info); + + return create_socket(msg.memory, size, &spi); +}; + +XFRM__Result f__XFRM__delete__policy(const SPDelInfo& pol_info){ + unsigned long spi = 0; + unsigned int payload_len; + int size; + + TTCN_Logger::log( TTCN_DEBUG,"###### Deleting policies from the database:"); + payload_len = NLA_ALIGN(sizeof(struct xfrm_userpolicy_id)); + size = NLMSG_SPACE(payload_len); + Message msg = Message(size); + + f_set_MessageHeader(msg.memory,XFRM_MSG_DELPOLICY,payload_len); + f_set_SP_delete_info(msg.memory, pol_info); + + return create_socket(msg.memory, size, &spi); +}; + +XFRM__Result f__XFRM__flush__policy(){ + unsigned long spi = 0; + const unsigned int payload_len = NLA_ALIGN(sizeof(struct xfrm_usersa_flush)); + int size = NLMSG_SPACE(payload_len); + Message msg = Message(size); + TTCN_Logger::log( TTCN_DEBUG,"###### Flushing the policy database"); + f_set_MessageHeader(msg.memory,XFRM_MSG_FLUSHPOLICY,payload_len); + + return create_socket(msg.memory, size, &spi); +}; + +XFRM__Result f__XFRM__allocate__SPI( + const AllocSPI__Info& info, + INTEGER& spi +){ + unsigned int payload_len = NLA_ALIGN(sizeof(struct xfrm_userspi_info)); + int size = NLMSG_SPACE(payload_len); + unsigned long spi_val = 0; + + TTCN_Logger::log( TTCN_DEBUG,"###### Getting a free SPI from the kernel."); + Message msg = Message(size); + f_set_MessageHeader(msg.memory,XFRM_MSG_ALLOCSPI,payload_len); + + + struct xfrm_userspi_info* sa = (struct xfrm_userspi_info*)NLMSG_DATA(msg.memory); + memset(sa,0,sizeof(struct xfrm_usersa_info)); + + //set destination address + int addr_family = f_set_IP_address(info.dst(), &sa->info.id.daddr); + if(addr_family >= 0){ + sa->info.family = sa->info.sel.family = addr_family; + }; //else default value will be set: 0.0.0.0 + + //set source address + addr_family = f_set_IP_address(info.src(), &sa->info.saddr); + if(addr_family >= 0){ + sa->info.family = sa->info.sel.family = addr_family; + }; //else default value will be set: 0.0.0.0 + + sa->info.sel.prefixlen_d = sa->info.sel.prefixlen_s = 0; + + //Setting default values for each parameter + //Some of the parameters are not configurable, but can be added later + sa->info.sel.ifindex = 0; + sa->info.sel.user = 0; + sa->info.id.spi = 0; + sa->info.id.proto = info.protocol(); + sa->info.mode = 0; + + sa->info.curlft.bytes = 0; + sa->info.curlft.packets = 0; + sa->info.curlft.add_time = 0; + sa->info.curlft.use_time = 0; + sa->info.stats.replay_window = 0; + sa->info.stats.replay = 0; + sa->info.stats.integrity_failed = 0; + + sa->info.seq = 0; + sa->info.reqid = 0; + sa->info.replay_window = sa->info.stats.replay_window; + sa->info.flags = 0; + sa->min = 0; + sa->max = 4294967294; + + if(info.range().ispresent()){ + sa->min = info.range()().min(); + sa->min = info.range()().max(); + }; + + XFRM__Result result = create_socket(msg.memory, size, &spi_val); + spi.set_long_long_val(spi_val); + return result; +}; + +} //namespace diff --git a/src/TCCIPsec_XFRM.hh b/src/TCCIPsec_XFRM.hh new file mode 100644 index 0000000..0e8fbf8 --- /dev/null +++ b/src/TCCIPsec_XFRM.hh @@ -0,0 +1,34 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +// +// File: TCCIPsec_XFRM.hh +// Description: TCC Useful Functions: IPsec XFRM Functions +// Rev: R30A +// Prodnr: CNL 113 472 +// +/////////////////////////////////////////////////////////////////////////////// + +#include "TCCIPsec_XFRM_Definitions.hh" +#ifdef LINUX + #include <linux/xfrm.h> +#else + #include <net/xfrm.h> +#endif + +using namespace TCCIPsec__XFRM__Definitions; + +void f_set_MessageBody_for_addSA(void*,const SAAddInfo&,const unsigned int,const unsigned int); +void f_set_MessageBody_for_deleteSA(void*,const SADelInfo&); + +void f_set_SP_add_info(void*,const SPAddInfo&); +void f_set_SP_delete_info(void*,const SPDelInfo&); + +int f_set_IP_address(CHARSTRING, xfrm_address_t*); +xfrm_lifetime_cfg f_set_IP_lifetime(Limits limits); diff --git a/src/TCCIPsec_XFRM_Definitions.ttcn b/src/TCCIPsec_XFRM_Definitions.ttcn new file mode 100644 index 0000000..67bcb89 --- /dev/null +++ b/src/TCCIPsec_XFRM_Definitions.ttcn @@ -0,0 +1,578 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +// +// File: TCCIPsec_XFRM_Definitions.ttcn +// Description: TCC Useful Functions: IPsec XFRM Functions +// Rev: R30A +// Prodnr: CNL 113 472 +// +/////////////////////////////////////////////////////////////////////////////// + +module TCCIPsec_XFRM_Definitions{ + external function f_XFRM_add_sa(in SAAddInfo pl_sa_info) return XFRM_Result; + external function f_XFRM_delete_sa(in SADelInfo pl_sa_info) return XFRM_Result; + external function f_XFRM_flush_sa() return XFRM_Result; + external function f_XFRM_add_policy(in SPAddInfo pl_pol_info) return XFRM_Result; + external function f_XFRM_delete_policy(in SPDelInfo pl_pol_info) return XFRM_Result; + external function f_XFRM_flush_policy() return XFRM_Result; + external function f_XFRM_allocate_SPI(in AllocSPI_Info pl_AllocSPI_info, inout integer pl_spi) return XFRM_Result; + +/////////////////////////////////////////////////////////////////////////////////// +// Type: NetworkAddress +// +// Purpose: +// Defines a record for using IP addresses with port and prefix number. +// +// Elements: +// ip_address - An IPv4 or IPv6 address (string). +// Not valid address form can result an error in the database. +// For example not inserting the new database entry. +// +// port_number - An integer used to specify a given port for the policies. +// address_prefix - An integer indivating the network prefix for the address. +// +/////////////////////////////////////////////////////////////////////////////////// +type record NetworkAddress{ + charstring ip_address, + integer port_number optional, + integer address_prefix optional +} + + +/////////////////////////////////////////////////////////////////////////////////// +// Type: TransportProtocol +// +// Purpose: +// Defines an enumerated value for selecting the Transport Protocol. +// For default value, the ANY choice is used in the protocol. +// +/////////////////////////////////////////////////////////////////////////////////// +type enumerated TransportProtocol{ + ANY (0), + ICMP (1), //IPPROTO_ICMP + TCP (6), //IPPROTO_TCP + UDP (17), //IPPROTO_UDP + DCCP (33), //IPPROTO_DCCP + GRE (47), //IPPROTO_GRE + ICMPV6 (58), //IPPROTO_ICMPV6 + SCTP (132) //IPPROTO_SCTP +} + + +/////////////////////////////////////////////////////////////////////////////////// +// Type: PolicyDirection +// +// Purpose: +// Defines the direction of a policy used on the packets. +// +///////////////////////////////////////////////////////////////////////////////// +type enumerated PolicyDirection{ + IN (0), //XFRM_POLICY_IN + OUT (1), //XFRM_POLICY_OUT + FWD (2) //XFRM_POLICY_FWD +} + + +/////////////////////////////////////////////////////////////////////////////////// +// Type: IPsecAlgorithms +// +// Purpose: +// Defines the encryption and authentication methods used in the Security +// Associations. +// +// Elements: +// auth - Defines an authentication method and the key used. +// enc - Defines an encryption method and the key used. +// +// Comment: +// Using Encryption without authentication is strongly discouraged, because +// it is insecure. +///////////////////////////////////////////////////////////////////////////////// +type record IPsecAlgorithms{ + Authentication auth optional, + Encryption enc optional +} + + +/////////////////////////////////////////////////////////////////////////////////// +// Type: IPSecProtocol +// +// Purpose: +// Defines the IPSec protocol used. +// +// Elements: +// ESP - Encapsulating Security Payloads: it provides origin authenticity, +// integrity and confidentiality protection of packets. +// AH - Authentication Header: It guarantees connectionless integrity and data +// origin authentication of IP packets +// COMP - IP Payload Compression: a low level compression protocol for IP datagrams +// Compression must be done before fragmenting or encrypting the packet. +///////////////////////////////////////////////////////////////////////////////// +type enumerated IPSecProtocol{ + ESP(50), //IPPROTO_ESP + AH(51), //IPPROTO_AH + COMP(108) //IPPROTO_COMP +} + +/////////////////////////////////////////////////////////////////////////////////// +// Type: IPSecKey +// +// Purpose: +// Defines a charstring or hexstring for the key used in ESP or AH. +// +/////////////////////////////////////////////////////////////////////////////////// +type union IPSecKey{ + charstring text, + hexstring hex +} + + +/////////////////////////////////////////////////////////////////////////////////// +// Type: Authentication +// +// Purpose: +// Defines the name of the authentication algorithm and the key used. +// +// Elements: +// name - An enumerated value for selecting the algorithm +// key - The used key for the authentication. It can be given in charstring +// or hexstring value. +// +/////////////////////////////////////////////////////////////////////////////////// +type record Authentication{ + AuthenticationAlgorithms name, + IPSecKey key +} + + +/////////////////////////////////////////////////////////////////////////////////// +// Type: AuthenticationAlgorithms +// +// Purpose: +// Defines an enumerated value for selecting the authentication alogrithm. +// +// Comment: +// The key lengths are next to each possible algorithm. +// +/////////////////////////////////////////////////////////////////////////////////// +type enumerated AuthenticationAlgorithms{ + NULL_AUTH (0), + HMAC_MD5 (1), //key length: 128 bits + HMAC_SHA1 (2), //key length: 160 bits + HMAC_SHA256 (3), //key length: 256 bits + HMAC_SHA384 (4), //key length: 384 bits + HMAC_SHA512 (5), //key length: 512 bits + HMAC_RMD160 (6) //key length: 160 bits +}; + + +/////////////////////////////////////////////////////////////////////////////////// +// Type: Encryption +// +// Purpose: +// Defines the name of the encryption algorithm and the key used. +// +// Elements: +// name - An enumerated value for selecting the algorithm +// key - The used key for the encryption. It can be given in charstring +// or hexstring value. +// +/////////////////////////////////////////////////////////////////////////////////// +type record Encryption{ + EncryptionAlgorithms name, + IPSecKey key +} + + +/////////////////////////////////////////////////////////////////////////////////// +// Type: EncryptionAlgorithms +// +// Purpose: +// Defines an enumerated value for selecting the encryption alogrithm. +// +// Comment: +// The key lengths are next to each possible algorithm. +// +/////////////////////////////////////////////////////////////////////////////////// +type enumerated EncryptionAlgorithms{ + NULL_ENCR (0), + CBC_AES (1), //key length: 128 bits + CBC_DES (2), //key length: 64 bits + CBC_3DES (3), //key length: 192 bits + CBC_CAST5 (4), //key length: 40-128 bits + CBC_BLOWFISH (5), //key length: 40-448 bits + CBC_SERPENT (6), //key length: 128-256 bits + CBC_CAMELLIA (7), //key length: 128-256 bits + CBC_TWOFISH (8) //key length: 128-256 bits +} + + +////////////////////////////////////////////////////////////////////////////////// +// Type: Mode +// +// Purpose: +// Defines an enumerated value for selecting the mode of the operation for the +// transform protocol.. +// +// Comment: +// BEET - Bound End-to-End Tunnel is for ESP only. +// +/////////////////////////////////////////////////////////////////////////////////// +type enumerated Mode{ + TRANSPORT (0), //XFRM_MODE_TRANSPORT + TUNNEL (1), //XFRM_MODE_TUNNEL + BEET (4) //XFRM_MODE_BEET +} + + +////////////////////////////////////////////////////////////////////////////////// +// Type: Share +// +// Purpose: +// Defines an enumerated value for selecting sharing mode. +// +// Comment: +// Should be ANY. In the current version, not used by the kernel, but required +// for forward compatibility.. +// +/////////////////////////////////////////////////////////////////////////////////// +type enumerated Share{ + ANY (0), //XFRM_SHARE_ANY: No limitations(default value) + SESSION (1), //XFRM_SHARE_SESSION: For this session only + USER (2), //XFRM_SHARE_USER: For this user only + UNIQUE (3) //XFRM_SHARE_UNIQUE: Use once +} + + +////////////////////////////////////////////////////////////////////////////////// +// Type: Action +// +// Purpose: +// Defines an enumerated value for allowing/blocking traffic +// +/////////////////////////////////////////////////////////////////////////////////// +type enumerated Action{ + ALLOW (0), //XFRM_POLICY_ALLOW + BLOCK (1) //XFRM_POLICY_BLOCK +} + + +////////////////////////////////////////////////////////////////////////////////// +// Type: Level +// +// Purpose: +// Defines an enumerated value for setting the level of the policy +// +// Comment: +// use - Indicates, that the policy should be used if there is an +// appropriate SA avaiable. (else the policy is bypassed) +// required - The policy has to be used. +// +/////////////////////////////////////////////////////////////////////////////////// +type enumerated Level{ + required (0), + use (1) +} + + +////////////////////////////////////////////////////////////////////////////////// +// Type: Template +// +// Purpose: +// Defines a record for the policy template. The behavior of the policy can be +// described with the templates. For example, the use of AH or ESP can be set +// via the templates. +// +// Elements: +// ip_version - Specifies the IP version +// src - Source address of the tunnel. Ignored in other cases. +// dst - Destination of the tunnel. It may be zero for transport mode. +// spi - Security Parameter Index, it is used to select the appropriate SA. +// The default value of SPI can be zero. +// reqid - Association between the policies and the SAs.(If a policy matches +// on a packet, then it will start searching for a matching SA based +// on the reqid value.) +// share - Selects the share mode(Default value: ANY, probably not used by +// the kernel, but it is required for forward compatibility.) +// ipsec - Defines the IPSec protocol used. +// mode - Transform mode. +// level - Sets the level of the policy. +/////////////////////////////////////////////////////////////////////////////////// +type record Template{ + NetworkAddress src optional, + NetworkAddress dst optional, + integer spi, + integer reqid optional, + Share share optional, + IPSecProtocol ipsec, + Mode mode, + Level level +} + + +////////////////////////////////////////////////////////////////////////////////// +// Type: Template_List +// +// Purpose: +// Defines a list of Templates. +// +/////////////////////////////////////////////////////////////////////////////////// +type set of Template Template_List; + + +////////////////////////////////////////////////////////////////////////////////// +// Type: Limits +// +// Purpose: +// With the help of th is record, time, packet and byte limits can be set for +// the policies and the SAs. +// +// Comment: +// soft vs hard: If the soft limit expire, then rekeying is required. If the +// hard limit expires, the entry from the database will be deleted. +// +// Elements: +// byte_limit - Defines a limit based on the sent/recieved bytes +// packet_limit - Defines a limit based on the sent/recieved packets +// add_expires_seconds - Defines a limit based on the time elapsed since insertion/update +/////////////////////////////////////////////////////////////////////////////////// +type record Limits{ + integer soft_byte_limit optional, + integer hard_byte_limit optional, + integer soft_packet_limit optional, + integer hard_packet_limit optional, + integer soft_add_expires_seconds optional, + integer hard_add_expires_seconds optional, + integer soft_use_expires_seconds optional, + integer hard_use_expires_seconds optional +} + +////////////////////////////////////////////////////////////////////////////////// +// Type: Encap_type +// +// Purpose: +// Encapsulates packets with protocol espinudp or espinudp-non-ike +// +// Comment: +// It uses source port, destination port and original address. +/////////////////////////////////////////////////////////////////////////////////// +type enumerated Encap_type{ + ESPINUDP_NON_IKE (1), + ESPINUDP (2) //Default value should be this +} + +////////////////////////////////////////////////////////////////////////////////// +// Type: NAT_T +// +// Purpose: +// Enables the usage of Network Address Traversal for the IPsec tunnel +// +// Elements: +// encap_type - Defines encapsulation protocol +// sport - Source port --> "hole" in the wall +// dport - Destination port --> "hole" in the wall +// oa - Original Adress +/////////////////////////////////////////////////////////////////////////////////// +type record NAT_T{ + Encap_type encap_type, //Default value should be ESPINUDP + integer sport, //Default value should be 4500 + integer dport, //Default value should be 4500 + charstring oa optional +} + +////////////////////////////////////////////////////////////////////////////////// +// Type: SAAdditionalInfo +// +// Purpose: +// Defines additional information regarding the Security Association creation. +// These are not mandatory parameters for creating a valid SA. +// +// Elements: +// sel_src and sel_dst - Selector address that is used to identify if a packet +// requires IPsec related actions. +// reqid - Also serves as an identification between the SP and SA +// limits - Lifetime limits for the Security Association +/////////////////////////////////////////////////////////////////////////////////// +type record SAAdditionalInfo{ + NetworkAddress sel_src optional, + NetworkAddress sel_dst optional, + integer reqid optional, //Policy<->SA connection, else selector + Limits limits optional +} + +////////////////////////////////////////////////////////////////////////////////// +// Type: SAAddInfo +// +// Purpose: +// Defines the basic information for creating a Security Assoctiation. +// +// Elements: +// update - if set to true and the SA already exists, it will be updated/overwritten +// if not exists, it will be created. +// protocol - Defines the used transport protocol +// ipsec - Defines the type of IPsec usage +// ipsec_agos - Defines the algorithms and keys +// mode - IPsec mode (tunneling or transport) +// spi - Security Parameter Index +// src - Source address +// dst - Destination adress +// nat_t - Enable NAT +// info - Defines additional settings +/////////////////////////////////////////////////////////////////////////////////// +type record SAAddInfo{ + boolean update optional, + TransportProtocol protocol, + IPSecProtocol ipsec, + IPsecAlgorithms ipsec_algos, + Mode mode, + integer spi, + NetworkAddress src, + NetworkAddress dst, + NAT_T nat_t optional, + SAAdditionalInfo info optional +} + +////////////////////////////////////////////////////////////////////////////////// +// Type: SADelInfo +// +// Purpose: +// Defines the basic information toidentiy and remove a Security Assoctiation. +// +// Elements: +// protocol - Defines the used transport protocol +// spi - Security Parameter Index +// src - Source address +// dst - Destination adress +/////////////////////////////////////////////////////////////////////////////////// +type record SADelInfo{ + IPSecProtocol proto, + integer spi, + NetworkAddress src, + NetworkAddress dst +} + +////////////////////////////////////////////////////////////////////////////////// +// Type: SPAdditionalInfo +// +// Purpose: +// Defines additional information regarding the Security Policy creation. +// These are not mandatory parameters for creating a valid SP. +// +// Elements: +// share - Defines the scope of the policy +// priority - Enables prioritization of SPs +// policy_action - Policy rule (ALLOW or BLOCK) +// index - Used for identification, similar to the selector +// interface_index - Enables the usage of an SP only for a specific interface +// limits - Lifetime limits for the Security Policy +/////////////////////////////////////////////////////////////////////////////////// +type record SPAdditionalInfo{ + Share share optional, + integer priority optional, + Action policy_action optional, + integer index optional, + integer interface_index optional, + Limits limits optional +} + +////////////////////////////////////////////////////////////////////////////////// +// Type: SPAddInfo +// +// Purpose: +// Defines the basic information for creating a Security Policy. +// +// Elements: +// update - if set to true and the SP already exists, it will be updated/overwritten +// if not exists, it will be created. +// protocol - Defines the used transport protocol +// src - Source address +// dst - Destination adress +// dir - Direction of the traffic +// tmpl - Defines Templates for the SP that is used for idetification +// info - Defines additional settings +/////////////////////////////////////////////////////////////////////////////////// +type record SPAddInfo{ + boolean update optional, + TransportProtocol protocol, + NetworkAddress src, + NetworkAddress dst, + PolicyDirection dir, + Template_List tmpl, + SPAdditionalInfo info optional +} + +////////////////////////////////////////////////////////////////////////////////// +// Type: SPDelInfo +// +// Purpose: +// Defines the basic information for identifying and removing a Security Policy. +// +// Elements: +// dir - Direction of the traffic +// protocol - Defines the used transport protocol +// src - Source address +// dst - Destination adress +/////////////////////////////////////////////////////////////////////////////////// +type record SPDelInfo{ + PolicyDirection dir, + TransportProtocol protocol, + NetworkAddress src, + NetworkAddress dst +} + +////////////////////////////////////////////////////////////////////////////////// +// Type: SPI_Range +// +// Purpose: +// Minimum and maximum value for SPI +/////////////////////////////////////////////////////////////////////////////////// +type record SPI_Range{ + integer min, + integer max +} + +////////////////////////////////////////////////////////////////////////////////// +// Type: AllocSPI_Info +// +// Purpose: +// Defines the basic information for allocating an SPI value. +// +// Elements: +// src - Source address +// dst - Destination adress +// protocol - IPsec protocol +// range - Range of the SPI +/////////////////////////////////////////////////////////////////////////////////// +type record AllocSPI_Info{ + charstring src, + charstring dst, + IPSecProtocol protocol, + SPI_Range range optional +} + +////////////////////////////////////////////////////////////////////////////////// +// Type: XFRM_Result +// +// Purpose: +// Serves as a return value for the TTCN-3 functions. It contains general result +// and in case of an error, some description on the error. +// +// Elements: +// result - If the execution is successful,the value is 0. +// msg - If error occurs before reaching the kernel or the error is in the +// communications with the kernel, then this contains information on it. +// If the reponse is negative, then it contains the message from the kernel. +/////////////////////////////////////////////////////////////////////////////////// +type record XFRM_Result{ + integer result, + charstring msg +} + +} diff --git a/src/TCCIPsec_XFRM_SA.cc b/src/TCCIPsec_XFRM_SA.cc new file mode 100644 index 0000000..0f4a3dc --- /dev/null +++ b/src/TCCIPsec_XFRM_SA.cc @@ -0,0 +1,324 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +// +// File: TCCIPsec_XFRM_SA.cc +// Description: TCC Useful Functions: IPsec XFRM Functions +// Rev: R30A +// Prodnr: CNL 113 472 +// +/////////////////////////////////////////////////////////////////////////////// +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <asm/types.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <errno.h> +#include <time.h> +#include <signal.h> + +#ifdef LINUX + #include <linux/netlink.h> +#else + #include <net/netlink.h> +#endif + +#include "TCCIPsec_XFRM_Definitions.hh" +#include "TCCIPsec_XFRM.hh" +#include "Logger.hh" + +using namespace TCCIPsec__XFRM__Definitions; + +//Sets the IP address to the addr parameter and returns the address family +int f_set_IP_address(CHARSTRING address, xfrm_address_t* addr){ + int temp = inet_pton(AF_INET,address,(void*)&addr->a4); + if(temp > 0){ + return AF_INET; + }else{ + temp = inet_pton(AF_INET6,address,(void*)&addr->a6); + if(temp > 0){ + return AF_INET6; + }else{ + TTCN_Logger::log( TTCN_DEBUG,"###### dst: "+address+" is not a well-formed IP address!"); + return -1; + }; + }; +} + +xfrm_lifetime_cfg f_set_IP_lifetime(Limits limits){ + //Set default values + xfrm_lifetime_cfg lft; + lft.soft_byte_limit = XFRM_INF; + lft.hard_byte_limit = XFRM_INF; + lft.soft_packet_limit = XFRM_INF; + lft.hard_packet_limit = XFRM_INF; + lft.soft_add_expires_seconds = 0; + lft.hard_add_expires_seconds = 0; + lft.soft_use_expires_seconds = 0; + lft.hard_use_expires_seconds = 0; + + if(limits.soft__byte__limit().ispresent()){ + lft.soft_byte_limit = limits.soft__byte__limit()(); + }; + if(limits.hard__byte__limit().ispresent()){ + lft.hard_byte_limit = limits.hard__byte__limit()(); + }; + if(limits.soft__packet__limit().ispresent()){ + lft.soft_packet_limit = limits.soft__packet__limit()(); + }; + if(limits.hard__packet__limit().ispresent()){ + lft.hard_packet_limit = limits.hard__packet__limit()(); + }; + if(limits.soft__add__expires__seconds().ispresent()){ + lft.soft_add_expires_seconds = limits.soft__add__expires__seconds()(); + }; + if(limits.hard__add__expires__seconds().ispresent()){ + lft.hard_add_expires_seconds = limits.hard__add__expires__seconds()(); + }; + if(limits.soft__use__expires__seconds().ispresent()){ + lft.soft_use_expires_seconds = limits.soft__use__expires__seconds()(); + }; + if(limits.hard__use__expires__seconds().ispresent()){ + lft.hard_use_expires_seconds = limits.hard__use__expires__seconds()(); + }; + + return lft; +} + +void f_process_additionalInfo( + xfrm_usersa_info* sa, + const SAAdditionalInfo& info +){ + if(info.sel__src().ispresent()){ + f_set_IP_address(info.sel__src()().ip__address(), &sa->sel.saddr); + if(info.sel__src()().address__prefix().ispresent())sa->sel.prefixlen_s = info.sel__src()().address__prefix()(); + if(info.sel__src()().port__number().ispresent()){ + sa->sel.sport = htons(info.sel__src()().port__number()()); + sa->sel.sport_mask = 0xffff; + }; + }; + + if(info.sel__dst().ispresent()){ + f_set_IP_address(info.sel__dst()().ip__address(), &sa->sel.daddr); + if(info.sel__dst()().address__prefix().ispresent())sa->sel.prefixlen_d = info.sel__dst()().address__prefix()(); + if(info.sel__dst()().port__number().ispresent()){ + sa->sel.dport = htons(info.sel__dst()().port__number()()); + sa->sel.dport_mask = 0xffff; + }; + }; + + if(info.reqid().ispresent()){ sa->reqid = info.reqid()().get_long_long_val(); }; + if(info.limits().ispresent()){ + sa->lft = f_set_IP_lifetime(info.limits()()); + }; + return; +} + +void f_set_encryptionInfo( + xfrm_algo* alg, + const Encryption& info, + int enc_key_len +){ + bool not_null = true; + switch(info.name()){ + case EncryptionAlgorithms::NULL__ENCR: {strcpy(alg->alg_name,"ecb(cipher_null)");alg->alg_key_len = 0;memcpy(alg->alg_key,"",0);not_null = false;break;} + case EncryptionAlgorithms::CBC__AES: {strcpy(alg->alg_name,"cbc(aes)");break;} + case EncryptionAlgorithms::CBC__DES: {strcpy(alg->alg_name,"cbc(des)");break;} + case EncryptionAlgorithms::CBC__3DES: {strcpy(alg->alg_name,"cbc(des3_ede)");break;} + case EncryptionAlgorithms::CBC__CAST5: {strcpy(alg->alg_name,"cbc(cast5)");break;} + case EncryptionAlgorithms::CBC__BLOWFISH: {strcpy(alg->alg_name,"cbc(blowfish)");break;} + case EncryptionAlgorithms::CBC__SERPENT: {strcpy(alg->alg_name,"cbc(serpent)");break;} + case EncryptionAlgorithms::CBC__CAMELLIA: {strcpy(alg->alg_name,"cbc(camellia)");break;} + case EncryptionAlgorithms::CBC__TWOFISH: {strcpy(alg->alg_name,"cbc(twofish)");break;} + default: { + strcpy(alg->alg_name,"ecb(cipher_null)"); + alg -> alg_key_len = 0; + memcpy(alg->alg_key,"",0); + not_null = false; + } + }; + + if(not_null){ + alg->alg_key_len = enc_key_len*8; + if(info.key().get_selection() == IPSecKey::ALT_text){ + memcpy(alg->alg_key,info.key().text(),enc_key_len); + } else { + memcpy(alg->alg_key,(const char*)(const unsigned char*)hex2oct(info.key().hex()),enc_key_len); + }; + }; + return; +} + +void f_set_authenticationInfo( + xfrm_algo* alg, + const Authentication& info, + int auth_key_len +){ + bool not_null = true; + switch(info.name()){ + case AuthenticationAlgorithms::NULL__AUTH: {strcpy(alg->alg_name,"digest_null");alg->alg_key_len = 0;memcpy(alg->alg_key,"",0);not_null = false;break;} + case AuthenticationAlgorithms::HMAC__MD5: {strcpy(alg->alg_name,"hmac(md5)");break;} + case AuthenticationAlgorithms::HMAC__SHA1: {strcpy(alg->alg_name,"hmac(sha1)");break;} + case AuthenticationAlgorithms::HMAC__SHA256: {strcpy(alg->alg_name,"hmac(sha256)");break;} + case AuthenticationAlgorithms::HMAC__SHA384: {strcpy(alg->alg_name,"hmac(sha384)");break;} + case AuthenticationAlgorithms::HMAC__SHA512: {strcpy(alg->alg_name,"hmac(sha512)");break;} + case AuthenticationAlgorithms::HMAC__RMD160: {strcpy(alg->alg_name,"hmac(rmd160)");break;} + default: { + strcpy(alg->alg_name,"ecb(cipher_null)"); + alg -> alg_key_len = 0; + memcpy(alg->alg_key,"",0); + not_null = false; + } + }; + + if(not_null){ + alg->alg_key_len = auth_key_len*8; + if(info.key().get_selection() == IPSecKey::ALT_text){ + memcpy(alg->alg_key,info.key().text(),auth_key_len); + } else { + memcpy(alg->alg_key,(const char*)(const unsigned char*)hex2oct(info.key().hex()),auth_key_len); + }; + }; + return; +} + +void f_set_MessageBody_for_addSA( + void* memo, + const SAAddInfo& sa_info, + const unsigned int enc_key_len, + const unsigned int auth_key_len +){ + struct xfrm_usersa_info* sa; + struct xfrm_algo* alg; + struct xfrm_encap_tmpl* nat; + struct nlattr* ahdr = NULL; + bool multiple_attr = false; + + sa = (struct xfrm_usersa_info*)NLMSG_DATA(memo); + memset(sa,0,sizeof(struct xfrm_usersa_info)); + + //set destination address + int addr_family = f_set_IP_address(sa_info.dst().ip__address(), &sa->id.daddr); + if(addr_family >= 0){ + sa->family = sa->sel.family = addr_family; + }; //else default value will be set: 0.0.0.0 + + //set source address + addr_family = f_set_IP_address(sa_info.src().ip__address(), &sa->saddr); + if(addr_family >= 0){ + sa->family = sa->sel.family = addr_family; + }; //else default value will be set: 0.0.0.0 + + sa->sel.prefixlen_d = sa->sel.prefixlen_s = 0; + + if(sa_info.protocol() != TransportProtocol::ANY){ + sa->sel.proto = sa_info.protocol(); + } else { + //in case of ANY no value should be defined + } + + //Setting default values for each parameter + //Some of the parameters are not configurable, but can be added later + sa->sel.ifindex = 0; + sa->sel.user = 0; + sa->id.spi = htonl(sa_info.spi().get_long_long_val()); + sa->id.proto = sa_info.ipsec(); + sa->mode = sa_info.mode(); + + sa->curlft.bytes = 0; + sa->curlft.packets = 0; + sa->curlft.add_time = 0; + sa->curlft.use_time = 0; + sa->stats.replay_window = 0; + sa->stats.replay = 0; + sa->stats.integrity_failed = 0; + + sa->seq = 0; + sa->reqid = 0; + sa->replay_window = sa->stats.replay_window; + sa->flags = 0; + + if(sa_info.info().ispresent()){ + f_process_additionalInfo(sa, sa_info.info()()); + }; + + if(sa_info.ipsec__algos().enc().ispresent()){ + TTCN_Logger::log( TTCN_DEBUG,"###### Encryption enabled."); + ahdr = (struct nlattr*)((char*)sa+NLA_ALIGN(sizeof(*sa))); + ahdr->nla_len = NLA_HDRLEN+sizeof(struct xfrm_algo)+enc_key_len; + ahdr->nla_type = XFRMA_ALG_CRYPT; + alg = (struct xfrm_algo*)((char*)ahdr+NLA_HDRLEN); + + f_set_encryptionInfo(alg, sa_info.ipsec__algos().enc()(),enc_key_len); + multiple_attr = true; + }; + + if(sa_info.ipsec__algos().auth().ispresent()){ + TTCN_Logger::log( TTCN_DEBUG,"###### Authentication enabled."); + if(multiple_attr){ahdr = (struct nlattr*)((char*)ahdr+NLA_ALIGN(ahdr->nla_len));} + else {ahdr = (struct nlattr*)((char*)sa+NLA_ALIGN(sizeof(*sa)));}; + ahdr->nla_len = NLA_HDRLEN+sizeof(struct xfrm_algo)+auth_key_len; + ahdr->nla_type = XFRMA_ALG_AUTH; + alg = (struct xfrm_algo*)((char*)ahdr+NLA_HDRLEN); + + f_set_authenticationInfo(alg, sa_info.ipsec__algos().auth()(),auth_key_len); + multiple_attr = true; + }; + + if(sa_info.nat__t().ispresent()){ + TTCN_Logger::log( TTCN_DEBUG,"###### NAT traversal enabled."); + if(multiple_attr){ahdr = (struct nlattr*)((char*)ahdr+NLA_ALIGN(ahdr->nla_len));} + else {ahdr = (struct nlattr*)((char*)sa+NLA_ALIGN(sizeof(*sa)));}; + ahdr->nla_len = NLA_HDRLEN+sizeof(*nat); + ahdr->nla_type = XFRMA_ENCAP; + nat = (struct xfrm_encap_tmpl*)((char*)ahdr+NLA_HDRLEN); + + nat->encap_type = sa_info.nat__t()().encap__type(), + nat->encap_sport = htons(sa_info.nat__t()().sport()); + nat->encap_dport = htons(sa_info.nat__t()().dport()); + + if(sa_info.nat__t()().oa().ispresent()){ + addr_family = f_set_IP_address(sa_info.nat__t()().oa()(), &nat->encap_oa); + }; + }; + + return; +} + +void f_set_MessageBody_for_deleteSA( + void* memo, + const SADelInfo& sa_info +){ + struct xfrm_usersa_id* sa; + xfrm_address_t* src; + struct nlattr* ahdr; + + sa = (struct xfrm_usersa_id*)NLMSG_DATA(memo); + memset(sa,0,sizeof(struct xfrm_usersa_id)); + + int addr_family = f_set_IP_address(sa_info.dst().ip__address(), &sa->daddr); + if(addr_family >= 0){ + sa->family = addr_family; + }; //else default value will be set: 0.0.0.0 + + sa->spi = htonl(sa_info.spi().get_long_long_val()); + + sa->proto = sa_info.proto(); + + ahdr = (struct nlattr*)((char*)sa+NLA_ALIGN(sizeof(*sa))); + ahdr->nla_len = NLA_HDRLEN+sizeof(*src); + ahdr->nla_type = XFRMA_SRCADDR; + src = (xfrm_address_t*)((char*)ahdr+NLA_HDRLEN); + + addr_family = f_set_IP_address(sa_info.src().ip__address(), src); + + return; +} diff --git a/src/TCCIPsec_XFRM_SP.cc b/src/TCCIPsec_XFRM_SP.cc new file mode 100644 index 0000000..b5597d2 --- /dev/null +++ b/src/TCCIPsec_XFRM_SP.cc @@ -0,0 +1,264 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +// +// File: TCCIPsec_XFRM_SP.cc +// Description: TCC Useful Functions: IPsec XFRM Functions +// Rev: R30A +// Prodnr: CNL 113 472 +// +/////////////////////////////////////////////////////////////////////////////// +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <asm/types.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <errno.h> +#include <time.h> +#include <signal.h> + +#ifdef LINUX + #include <linux/netlink.h> +#else + #include <net/netlink.h> +#endif + +#include "TCCIPsec_XFRM_Definitions.hh" +#include "TCCIPsec_XFRM.hh" +#include "Logger.hh" + +using namespace TCCIPsec__XFRM__Definitions; + +void f_process_additionalInfo( + xfrm_userpolicy_info* pol, + const SPAdditionalInfo& info +){ + if(info.share().ispresent()){pol->share = info.share()();}; + if(info.priority().ispresent()){pol->priority = info.priority()();}; + if(info.policy__action().ispresent()){pol->action = info.policy__action()();}; + if(info.index().ispresent()){pol->index = info.index()();}; + if(info.interface__index().ispresent()){pol->sel.ifindex = info.interface__index()();}; + + if(info.limits().ispresent()){ + Limits limits = info.limits(); + if(limits.soft__byte__limit().ispresent()){pol->lft.soft_byte_limit = limits.soft__byte__limit()();}; + if(limits.hard__byte__limit().ispresent()){pol->lft.hard_byte_limit = limits.hard__byte__limit()();}; + if(limits.soft__packet__limit().ispresent()){pol->lft.soft_packet_limit = limits.soft__packet__limit()();}; + if(limits.hard__packet__limit().ispresent()){pol->lft.hard_packet_limit = limits.hard__packet__limit()();}; + if(limits.soft__add__expires__seconds().ispresent()){pol->lft.soft_add_expires_seconds = limits.soft__add__expires__seconds()();}; + if(limits.hard__add__expires__seconds().ispresent()){pol->lft.hard_add_expires_seconds = limits.hard__add__expires__seconds()();}; + }; + + return; +} + +void f_add_template( + xfrm_user_tmpl* xTmpl, + const Template tmpl, + int share, + bool ipv4 +){ + if(tmpl.dst().ispresent()){ + f_set_IP_address(tmpl.dst()().ip__address(), &xTmpl->id.daddr); + }else{ + if(ipv4){ + inet_pton(AF_INET,"0.0.0.0",(void*)&xTmpl->id.daddr.a4); + }else{ + inet_pton(AF_INET6,"00:00:00:00:00:00:00:00",(void*)&xTmpl->id.daddr.a6); + }; + }; + + if(tmpl.src().ispresent()){ + f_set_IP_address(tmpl.src()().ip__address(), &xTmpl->saddr); + }else{ + if(ipv4){ + inet_pton(AF_INET,"0.0.0.0",(void*)&xTmpl->saddr.a4); + }else{ + inet_pton(AF_INET6,"00:00:00:00:00:00:00:00",(void*)&xTmpl->saddr.a6); + }; + }; + + xTmpl->id.spi = htonl(tmpl.spi().get_long_long_val()); + xTmpl->id.proto = tmpl.ipsec(); + + if(ipv4)xTmpl->family = AF_INET; + else xTmpl->family = AF_INET6; + + if(tmpl.reqid().ispresent())xTmpl->reqid = tmpl.reqid()().get_long_long_val(); + else xTmpl->reqid = 0; //0:require else:unique + + xTmpl->mode = tmpl.mode(); + + if(tmpl.share().ispresent()){ + xTmpl->share = tmpl.share()(); + } else xTmpl->share = share; + + xTmpl->optional = 0; + switch(tmpl.level()){ + case Level::use:{xTmpl->optional = 1;break;} + default: {xTmpl->optional = 0;} //Level -- 0:required 1:use + }; + + xTmpl->aalgos = (~(__u32)0); + xTmpl->ealgos = (~(__u32)0); + xTmpl->calgos = (~(__u32)0); + return; +} + +void f_set_SP_add_info( + void* memo, + const SPAddInfo& pol_info +){ + struct xfrm_userpolicy_info* pol; + struct xfrm_user_tmpl* tmpl = NULL; + struct nlattr* ahdr; + bool ipv4 = true; + int numberOfTmpls = pol_info.tmpl().size_of(); + + pol = (struct xfrm_userpolicy_info*)NLMSG_DATA(memo); + memset(pol,0,sizeof(struct xfrm_userpolicy_info)); + + int addr_family = f_set_IP_address(pol_info.dst().ip__address(), &pol->sel.daddr); + if(addr_family >= 0){ + pol->sel.family = addr_family; + if(addr_family == AF_INET){ + pol->sel.prefixlen_d = 32; + ipv4 = true; + } else { + pol->sel.prefixlen_d = 128; + ipv4 = false; + }; + }; //else default value will be set: 0.0.0.0 + + addr_family = f_set_IP_address(pol_info.src().ip__address(), &pol->sel.saddr); + if(addr_family >= 0){ + pol->sel.family = addr_family; + if(addr_family == AF_INET){ + pol->sel.prefixlen_s = 32; + } else { + pol->sel.prefixlen_s = 128; + }; + }; //else default value will be set: 0.0.0.0 + + if(pol_info.dst().address__prefix().ispresent()){pol->sel.prefixlen_d = pol_info.dst().address__prefix()();}; + if(pol_info.src().address__prefix().ispresent()){pol->sel.prefixlen_s = pol_info.src().address__prefix()();}; + if(pol_info.dst().port__number().ispresent()){ + pol->sel.dport = htons(pol_info.dst().port__number()()); + pol->sel.dport_mask = 0xffff; + }; + if(pol_info.src().port__number().ispresent()){ + pol->sel.sport = htons(pol_info.src().port__number()()); + pol->sel.sport_mask = 0xffff; + }; + + pol->sel.ifindex = 0; + pol->sel.user = 0; + + if(pol_info.protocol() != TransportProtocol::ANY){ + pol->sel.proto = pol_info.protocol(); + } else { + //in case of ANY, no value should be defined + } + + //Setting default lifetime values + pol->lft.soft_byte_limit = XFRM_INF; + pol->lft.hard_byte_limit = XFRM_INF; + pol->lft.soft_packet_limit = XFRM_INF; + pol->lft.hard_packet_limit = XFRM_INF; + pol->lft.soft_add_expires_seconds = 0; + pol->lft.hard_add_expires_seconds = 0; + pol->lft.soft_use_expires_seconds = 0; + pol->lft.hard_use_expires_seconds = 0; + + pol->curlft.bytes = 0; + pol->curlft.packets = 0; + pol->curlft.add_time = 0; + pol->curlft.use_time = 0; + + pol->index = 0; + + pol->share = XFRM_SHARE_ANY; + pol->priority = 0; + pol->action = XFRM_POLICY_ALLOW; + pol->flags = 0; + + pol->dir = pol_info.dir(); + + if(pol_info.info().ispresent()){ + f_process_additionalInfo(pol, pol_info.info()()); + }; + + Template__List list = pol_info.tmpl(); + + ahdr = (struct nlattr*)((char*)pol+NLA_ALIGN(sizeof(*pol))); + ahdr->nla_len = NLA_HDRLEN+sizeof(*tmpl)*numberOfTmpls; + ahdr->nla_type = XFRMA_TMPL; + + for(int i = 0;i<numberOfTmpls;i++){ + TTCN_Logger::log( TTCN_DEBUG,"###### %d. template:",i+1); + if(i>0){ + tmpl = (struct xfrm_user_tmpl*)((char*)tmpl+NLA_ALIGN(sizeof(*tmpl))); + } else { + tmpl = (struct xfrm_user_tmpl*)((char*)ahdr+NLA_HDRLEN); + }; + + f_add_template(tmpl,list[i],pol->share,ipv4); + }; + return; +} + +void f_set_SP_delete_info( + void* memo, + const SPDelInfo& pol_info +){ + struct xfrm_userpolicy_id* pol; + int temp; + + pol = (struct xfrm_userpolicy_id*)NLMSG_DATA(memo); + memset(pol,0,sizeof(struct xfrm_userpolicy_id)); + + int addr_family = f_set_IP_address(pol_info.dst().ip__address(), &pol->sel.daddr); + if(addr_family >= 0){ + pol->sel.family = addr_family; + if(addr_family == AF_INET){ + pol->sel.prefixlen_d = 32; + } else { + pol->sel.prefixlen_d = 128; + }; + }; //else default value will be set: 0.0.0.0 + + + temp = inet_pton(AF_INET,pol_info.src().ip__address(),(void*)&pol->sel.saddr.a4); + if(temp > 0){ + pol->sel.family = AF_INET; + pol->sel.prefixlen_s = 32; + }else{ + temp = inet_pton(AF_INET6,pol_info.src().ip__address(),(void*)&pol->sel.saddr.a6); + if(temp > 0){ + pol->sel.family = AF_INET6; + pol->sel.prefixlen_s = 128; + }else{ + TTCN_Logger::log( TTCN_DEBUG,"###### src: "+pol_info.dst().ip__address()+" is not a well-formed IP address!"); + }; + }; + + if(pol_info.dst().address__prefix().ispresent()){pol->sel.prefixlen_d = pol_info.dst().address__prefix()();}; + if(pol_info.src().address__prefix().ispresent()){pol->sel.prefixlen_s = pol_info.src().address__prefix()();}; + + if(pol_info.dst().port__number().ispresent())pol->sel.dport = htons(pol_info.dst().port__number()()); + if(pol_info.src().port__number().ispresent())pol->sel.sport = htons(pol_info.src().port__number()()); + pol->sel.dport_mask = pol->sel.sport_mask = 0xffff; + + pol->sel.proto = pol_info.protocol(); + + pol->dir = pol_info.dir(); +} + diff --git a/src/TCCInterface.cc b/src/TCCInterface.cc index 14c57f3..5d3d915 100644 --- a/src/TCCInterface.cc +++ b/src/TCCInterface.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2012 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCInterface.cc // Description: TCC Useful Functions: Interface Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2012-10-18 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCInterface_Functions.ttcn b/src/TCCInterface_Functions.ttcn index 3243f4f..1d3c0a3 100644 --- a/src/TCCInterface_Functions.ttcn +++ b/src/TCCInterface_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2016 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCInterface_Functions.ttcn // Description: TCC Useful Functions: Interface Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2016-06-06 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCInterface_ip.h b/src/TCCInterface_ip.h index c1a35a0..5eaee6d 100644 --- a/src/TCCInterface_ip.h +++ b/src/TCCInterface_ip.h @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2009 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCInterface_ip.h // Description: TCC Useful Functions: Interface Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2009-02-02 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// @@ -277,7 +274,9 @@ static int dnet_pton1(const char *src, struct dn_naddr *dna) if ((pos == 0) || (node > 1023)) return 0; dna->a_len = 2; - *(u_int16_t *)dna->a_addr = dn_htons((area << 10) | node); + u_int16_t ui16 = dn_htons((area << 10) | node); + dna->a_addr[0] = ui16; + dna->a_addr[1] = ui16 >> 8; return 1; } diff --git a/src/TCCMaths.cc b/src/TCCMaths.cc index 4d0aaad..28afd8c 100644 --- a/src/TCCMaths.cc +++ b/src/TCCMaths.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2007 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCMaths.cc // Description: TCC Useful Functions: Maths Functions. -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2007-03-07 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// @@ -25,6 +22,35 @@ using namespace TCCMaths__GenericTypes; namespace TCCMaths__Functions { +/////////////////////////////////////////////////////////////////////////////// +//template for count min or max value of list +/////////////////////////////////////////////////////////////////////////////// +template<typename T_list> +T_list f_minmax(const T_list& list, bool min) +{ + T_list toret; + toret[1] = -1; + toret[0] = 0; + + int len; + if(!list.is_bound() or ((len = list.size_of()) == 0)) + { + return toret; + } + + toret[0] = list[0]; + toret[1] = 0; + + for(int i=1 ; i<len ; ++i) + { + if(min?toret[0] > list[i]:toret[0] < list[i]) + { + toret[0] = list[i]; + toret[1] = i; + } + } + return toret; +} /////////////////////////////////////////////////////////////////////////////// // Function: f__maxIL // @@ -47,22 +73,7 @@ namespace TCCMaths__Functions { /////////////////////////////////////////////////////////////////////////////// IntegerList f__maxIL(const IntegerList& ilist) { - IntegerList toret; - - toret[0] = 0; - toret[1] = -1; - if(!ilist.is_bound()) return toret; - int len = ilist.size_of(); - - int m = - 0xffff; - for(int i=0;i<len;i++) - if(ilist[i]>m) - { - m = ilist[i]; - toret[1] = i; - } - toret[0] = m; - return toret; + return f_minmax(ilist, false); } /////////////////////////////////////////////////////////////////////////////// @@ -88,20 +99,7 @@ IntegerList f__maxIL(const IntegerList& ilist) /////////////////////////////////////////////////////////////////////////////// IntegerList f__minIL(const IntegerList& ilist) { - IntegerList toret; - toret[0] = 0; - toret[1] = -1; - if(!ilist.is_bound()) return toret; - int len = ilist.size_of(); - int m = 0xffff; - for(int i=0;i<len;i++) - if(ilist[i]<m) - { - m = ilist[i]; - toret[1] = i; - } - toret[0] = m; - return toret; + return f_minmax(ilist, true); } /////////////////////////////////////////////////////////////////////////////// @@ -127,21 +125,7 @@ IntegerList f__minIL(const IntegerList& ilist) /////////////////////////////////////////////////////////////////////////////// FloatList f__maxFL(const FloatList& flist) { - FloatList toret; - toret[0] = 0.0; - toret[1] = -1.0; - if(!flist.is_bound()) return toret; - int i, len = flist.size_of(); - - double m = -1.7E308; - for(i=0;i<len;i++) - if(flist[i]>m) - { - m = flist[i]; - toret[1] = (double)i; - } - toret[0] = m; - return toret; + return f_minmax(flist,false); } /////////////////////////////////////////////////////////////////////////////// @@ -167,20 +151,27 @@ FloatList f__maxFL(const FloatList& flist) /////////////////////////////////////////////////////////////////////////////// FloatList f__minFL(const FloatList& flist) { - FloatList toret; - toret[0] = 0.0; - toret[1] = -1.0; - if(!flist.is_bound()) return toret; - unsigned int i, len = (unsigned int)flist.size_of(); - double m = 1.7E308; - for(i=0;i<len;i++) - if(flist[i]<m) - { - m = flist[i]; - toret[1] = (double)i; - } - toret[0] = m; - return toret; + return f_minmax(flist, true); +} +/////////////////////////////////////////////////////////////////////////////// +//template for count average value of list +/////////////////////////////////////////////////////////////////////////////// +template<typename T_list> +FLOAT f_average(const T_list& list) +{ + int len; + if(!list.is_bound() or ((len = list.size_of()) == 0)) + { + return 0.0; + } + + int i; + double toret = 0.0; + for(i=0;i<len;++i) + { + toret += (double)list[i]; + } + return toret/(double)len; } /////////////////////////////////////////////////////////////////////////////// @@ -204,12 +195,7 @@ FloatList f__minFL(const FloatList& flist) /////////////////////////////////////////////////////////////////////////////// FLOAT f__averageFL(const FloatList& flist) { - if(!flist.is_bound()) return FLOAT(); - double toret = 0.0; - int i, len = flist.size_of(); - if(len==0) return FLOAT(); - for(i=0;i<len;i++) toret += flist[i]; - return FLOAT(toret / (double)len); + return f_average(flist); } /////////////////////////////////////////////////////////////////////////////// @@ -233,157 +219,177 @@ FLOAT f__averageFL(const FloatList& flist) /////////////////////////////////////////////////////////////////////////////// FLOAT f__averageIL(const IntegerList& ilist) { - int toret = 0; - int i, len = ilist.size_of(); - if(len == 0) return FLOAT(); - for(i=0;i<len;i++) toret += ilist[i]; - return FLOAT(((double)toret / (double)len)); + return f_average(ilist); +} +/////////////////////////////////////////////////////////////////////////////// +// template for update lists +/////////////////////////////////////////////////////////////////////////////// +template<typename T_list> +void f_update(T_list& head, const T_list& tail) +{ + if(!tail.is_bound()) + { + return; + } + + unsigned int i, count, len = tail.size_of(); + if(head.is_bound()) + { + count = (unsigned int)head.size_of(); + } else { + count = 0; + } + head.set_size(count + len); + for(i=0;i<len;++i) + { + head[count] = tail[i]; + ++count; + } } /////////////////////////////////////////////////////////////////////////////// -// Function: f__stdFL +// Function: f__updateFL // // Purpose: -// Return the normalized standard deviation of float list -// (so the average square distance from the center of elements in the list) +// Append tail to the end of head (head return as inout) // // Parameters: -// flist - *in* <FloatList> - float list +// head - *in* <FloatList> - first part of the float list +// tail - *in* <FloatList> - second part of the float list // // Return Value: -// float - normalized, standard derivate +// - // // Errors: // - // // Detailed description: -// E.g. list = {2.0, 4.0} -// -// u = (2.0 + 4.0) / 2 <- *center of elements in the list* -// -// len = sizeof(list) -// -// [ ( (2.0-u)^2 + (4.0-u)^2 ) / len ] ^ (0.5) +// - // /////////////////////////////////////////////////////////////////////////////// -FLOAT f__stdFL(const FloatList& flist) +void f__updateFL(FloatList& head, const FloatList& tail) { - if(!flist.is_bound()) return FLOAT(); - double toret = 0.0; - int i, len = flist.size_of(); - if(len == 0) return FLOAT(); - double u = (double)TCCMaths__Functions::f__averageFL(flist); - for(i=0;i<len;i++) toret += pow((double)flist[i]-u,2.0); - return FLOAT(pow(toret/((double)len-1),0.5)); + f_update(head,tail); } /////////////////////////////////////////////////////////////////////////////// -// Function: f__stdFLL +// Function: f__updateIL // // Purpose: -// Return the normalized standard deviation of float list using custom -// center -// (so it is the average square distance from a user defined central value) +// Append tail to the end of head (head return as inout) // // Parameters: -// u - *in* *float* - user defined central value -// flist - *in* <FloatList> - float list +// head - *in* <IntegerList> - first part of the integer list +// tail - *in* <IntegerList> - second part of the integer list // // Return Value: -// float - normalized, standard derivate +// - // // Errors: // - // // Detailed description: -// Note: u is the average value of flist and has to be calculated -// before a call to this function -// -// E.g. list = {2.0, 4.0} -// -// u <- *user input* -// -// len = sizeof(list) -// -// [ ( (2.0-u)^2 + (4.0-u)^2 ) / len ] ^ (0.5) +// - // /////////////////////////////////////////////////////////////////////////////// -FLOAT f__stdFLL(const FloatList& flist, const FLOAT& u) +void f__updateIL(IntegerList& head, const IntegerList& tail) +{ + f_update(head,tail); +} +/////////////////////////////////////////////////////////////////////////////// +//template for count corrected standard deviation +/////////////////////////////////////////////////////////////////////////////// +template<typename T_list> +FLOAT f_std(const T_list& list, const FLOAT& in_u = FLOAT()) { - if(!flist.is_bound()) FLOAT(); - double toret = 0.0; - int i, len = flist.size_of(); - if(len == 0) return FLOAT(); - for(i=0;i<len;i++) toret += pow((double)flist[i]-(double)u,2.0); - return FLOAT(pow(toret/((double)(len-1)),0.5)); + int len; + if(!list.is_bound() or ((len = list.size_of()) < 2)) + { + return 0.0; + } + + double u, toret = 0.0; + if (!in_u.is_bound()) + { + u = f_average(list); + } else { + u = in_u; + } + double x; + for(int i=0;i<len;++i) + { + x = (double)list[i]-u; + toret += x*x; + } + + return pow(toret/(double)(len-1),0.5); } /////////////////////////////////////////////////////////////////////////////// -// Function: f__updateFL +// Function: f__stdFL // // Purpose: -// Append tail to the end of head (head return as inout) +// Return the normalized standard deviation of float list +// (so the average square distance from the center of elements in the list) // // Parameters: -// head - *in* <FloatList> - first part of the float list -// tail - *in* <FloatList> - second part of the float list +// flist - *in* <FloatList> - float list // // Return Value: -// - +// float - normalized, standard derivate // // Errors: // - // // Detailed description: -// - +// E.g. list = {2.0, 4.0} +// +// u = (2.0 + 4.0) / 2 <- *center of elements in the list* +// +// len = sizeof(list) +// +// [ ( (2.0-u)^2 + (4.0-u)^2 ) / len ] ^ (0.5) // /////////////////////////////////////////////////////////////////////////////// -void f__updateFL(FloatList& head, const FloatList& tail) +FLOAT f__stdFL(const FloatList& flist) { - unsigned int i, count, len; - if(!tail.is_bound()) return; - len = tail.size_of(); - if(head.is_bound()) count = (unsigned int)head.size_of(); - else count = 0; - for(i=0;i<len;i++) - { - head[count] = tail[i]; - count++; - } + return f_std(flist); } /////////////////////////////////////////////////////////////////////////////// -// Function: f__updateIL +// Function: f__stdFLL // // Purpose: -// Append tail to the end of head (head return as inout) +// Return the normalized standard deviation of float list using custom +// center +// (so it is the average square distance from a user defined central value) // // Parameters: -// head - *in* <IntegerList> - first part of the integer list -// tail - *in* <IntegerList> - second part of the integer list +// u - *in* *float* - user defined central value +// flist - *in* <FloatList> - float list // // Return Value: -// - +// float - normalized, standard derivate // // Errors: // - // // Detailed description: -// - +// Note: u is the average value of flist and has to be calculated +// before a call to this function +// +// E.g. list = {2.0, 4.0} +// +// u <- *user input* +// +// len = sizeof(list) +// +// [ ( (2.0-u)^2 + (4.0-u)^2 ) / len ] ^ (0.5) // /////////////////////////////////////////////////////////////////////////////// -void f__updateIL(IntegerList& head, const IntegerList& tail) +FLOAT f__stdFLL(const FloatList& flist, const FLOAT& u) { - unsigned int i, count, len; - if(!tail.is_bound()) return; - len = tail.size_of(); - if(head.is_bound()) count = (unsigned int)head.size_of(); - else count = 0; - for(i=0;i<len;i++) - { - head[count] = tail[i]; - count++; - } + return f_std(flist,u); } /////////////////////////////////////////////////////////////////////////////// @@ -415,11 +421,7 @@ void f__updateIL(IntegerList& head, const IntegerList& tail) /////////////////////////////////////////////////////////////////////////////// FLOAT f__stdIL(const IntegerList& ilist) { - double toret = 0.0; - int i, len = ilist.size_of(); - double u = (double)TCCMaths__Functions::f__averageIL(ilist); - for(i=0;i<len;i++) toret += pow((double)ilist[i]-u,2.0); - return FLOAT(pow(toret/((double)len-1),0.5)); + return f_std(ilist); } /////////////////////////////////////////////////////////////////////////////// @@ -454,12 +456,7 @@ FLOAT f__stdIL(const IntegerList& ilist) /////////////////////////////////////////////////////////////////////////////// FLOAT f__stdILL(const IntegerList& ilist, const FLOAT& u) { - if(!ilist.is_bound()) FLOAT(); - double toret = 0.0; - int i, len = ilist.size_of(); - if(len == 0) return FLOAT(); - for(i=0;i<len;i++) toret += pow((double)ilist[i]-(double)u,2.0); - return FLOAT(pow(toret/((double)(len-1)),0.5)); + return f_std(ilist,u); } /////////////////////////////////////////////////////////////////////////////// @@ -491,17 +488,20 @@ FLOAT f__stdILL(const IntegerList& ilist, const FLOAT& u) /////////////////////////////////////////////////////////////////////////////// FloatList f__sinVL(const FLOAT& freq, const FLOAT& altitude, const FLOAT& start__val, const INTEGER& len, const FLOAT& step) { - double pi = 3.1415926535; - int i; - double tmp = (double)start__val; - FloatList toret; - for(i=0;i<(int)len;i++) + int i; + double tmp = start__val; + FloatList toret; + double common = 2.0 * M_PI * freq; + if (len > 0) + { + toret.set_size(len); + for ( i = 0; i < len; ++i) { - toret[i] = (double)altitude * sin(2.0 * pi * (double)freq * tmp); - tmp += (double)step; + toret[i] = altitude * sin(common * tmp); + tmp += step; } - - return (toret); + } + return toret; } /////////////////////////////////////////////////////////////////////////////// @@ -533,17 +533,20 @@ FloatList f__sinVL(const FLOAT& freq, const FLOAT& altitude, const FLOAT& start_ /////////////////////////////////////////////////////////////////////////////// FloatList f__cosVL(const FLOAT& freq, const FLOAT& altitude, const FLOAT& start__val, const INTEGER& len, const FLOAT& step) { - double pi = 3.1415926535; - int i; - double tmp = (double)start__val; - FloatList toret; - for(i=0;i<(int)len;i++) + int i; + double tmp = start__val; + FloatList toret; + double common = 2.0 * M_PI * freq; + if (len > 0) + { + toret.set_size(len); + for ( i = 0; i < len; ++i) { - toret[i] = (double)altitude * cos(2.0 * pi * (double)freq * tmp); - tmp += (double)step; + toret[i] = altitude * cos(common * tmp); + tmp += step; } - - return (toret); + } + return toret; } /////////////////////////////////////////////////////////////////////////////// @@ -567,7 +570,7 @@ FloatList f__cosVL(const FLOAT& freq, const FLOAT& altitude, const FLOAT& start_ /////////////////////////////////////////////////////////////////////////////// FLOAT f__sin(const FLOAT& angle) { - return FLOAT(sin(angle)); + return sin(angle); } /////////////////////////////////////////////////////////////////////////////// @@ -591,7 +594,7 @@ FLOAT f__sin(const FLOAT& angle) /////////////////////////////////////////////////////////////////////////////// FLOAT f__cos(const FLOAT& angle) { - return FLOAT(cos(angle)); + return cos(angle); } /////////////////////////////////////////////////////////////////////////////// @@ -615,7 +618,7 @@ FLOAT f__cos(const FLOAT& angle) /////////////////////////////////////////////////////////////////////////////// FLOAT f__asin(const FLOAT& val) { - return FLOAT(asin(val)); + return asin(val); } /////////////////////////////////////////////////////////////////////////////// @@ -639,7 +642,7 @@ FLOAT f__asin(const FLOAT& val) /////////////////////////////////////////////////////////////////////////////// FLOAT f__acos(const FLOAT& val) { - return FLOAT(acos(val)); + return acos(val); } /////////////////////////////////////////////////////////////////////////////// @@ -664,7 +667,7 @@ FLOAT f__acos(const FLOAT& val) /////////////////////////////////////////////////////////////////////////////// FLOAT f__powFF(const FLOAT& base, const FLOAT& expo) { - return FLOAT(pow(base, expo)); + return pow(base, expo); } /////////////////////////////////////////////////////////////////////////////// @@ -689,7 +692,7 @@ FLOAT f__powFF(const FLOAT& base, const FLOAT& expo) /////////////////////////////////////////////////////////////////////////////// INTEGER f__powII(const INTEGER& base, const INTEGER& expo) { - return INTEGER((int)pow(base, expo)); + return float2int(pow(int2float(base), int2float(expo))); } /////////////////////////////////////////////////////////////////////////////// @@ -714,7 +717,7 @@ INTEGER f__powII(const INTEGER& base, const INTEGER& expo) /////////////////////////////////////////////////////////////////////////////// FLOAT f__powIF(const INTEGER& base, const FLOAT& expo) { - return FLOAT(pow(base, expo)); + return pow(int2float(base), expo); } /////////////////////////////////////////////////////////////////////////////// @@ -739,7 +742,7 @@ FLOAT f__powIF(const INTEGER& base, const FLOAT& expo) /////////////////////////////////////////////////////////////////////////////// FLOAT f__powFI(const FLOAT& base, const INTEGER& expo) { - return FLOAT(pow(base, expo)); + return pow(base, int2float(expo)); } /////////////////////////////////////////////////////////////////////////////// @@ -763,7 +766,7 @@ FLOAT f__powFI(const FLOAT& base, const INTEGER& expo) /////////////////////////////////////////////////////////////////////////////// FLOAT f__sqrF(const FLOAT& base) { - return FLOAT(base*base); + return base*base; } /////////////////////////////////////////////////////////////////////////////// @@ -787,7 +790,7 @@ FLOAT f__sqrF(const FLOAT& base) /////////////////////////////////////////////////////////////////////////////// INTEGER f__sqrI(const INTEGER& base) { - return INTEGER(base*base); + return base*base; } /////////////////////////////////////////////////////////////////////////////// @@ -811,7 +814,7 @@ INTEGER f__sqrI(const INTEGER& base) /////////////////////////////////////////////////////////////////////////////// FLOAT f__sqrtF(const FLOAT& base) { - return FLOAT(sqrt(base)); + return sqrt(base); } /////////////////////////////////////////////////////////////////////////////// @@ -835,7 +838,7 @@ FLOAT f__sqrtF(const FLOAT& base) /////////////////////////////////////////////////////////////////////////////// FLOAT f__sqrtI(const INTEGER& base) { - return FLOAT(sqrt((double)base)); + return sqrt(int2float(base)); } /////////////////////////////////////////////////////////////////////////////// @@ -859,7 +862,7 @@ FLOAT f__sqrtI(const INTEGER& base) /////////////////////////////////////////////////////////////////////////////// INTEGER f__ceil(const FLOAT& val) { - return INTEGER((int)ceil(val)); + return float2int(ceil(val)); } /////////////////////////////////////////////////////////////////////////////// @@ -883,7 +886,7 @@ INTEGER f__ceil(const FLOAT& val) /////////////////////////////////////////////////////////////////////////////// INTEGER f__floor(const FLOAT& val) { - return INTEGER((int)floor(val)); + return float2int(floor(val)); } /////////////////////////////////////////////////////////////////////////////// @@ -907,7 +910,7 @@ INTEGER f__floor(const FLOAT& val) /////////////////////////////////////////////////////////////////////////////// FLOAT f__exp(const FLOAT& val) { - return FLOAT(exp(val)); + return exp(val); } /////////////////////////////////////////////////////////////////////////////// @@ -931,7 +934,7 @@ FLOAT f__exp(const FLOAT& val) /////////////////////////////////////////////////////////////////////////////// FLOAT f__log(const FLOAT& val) { - return FLOAT(log(val)); + return log(val); } } diff --git a/src/TCCMaths_Functions.ttcn b/src/TCCMaths_Functions.ttcn index 889f6f5..ba9fa56 100644 --- a/src/TCCMaths_Functions.ttcn +++ b/src/TCCMaths_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2008 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCMaths_Functions.ttcn // Description: TCC Useful Functions: Math Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2008-12-10 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCMaths_GenericTypes.ttcn b/src/TCCMaths_GenericTypes.ttcn index 2197a64..3d78306 100644 --- a/src/TCCMaths_GenericTypes.ttcn +++ b/src/TCCMaths_GenericTypes.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2007 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCMaths_GenericTypes.ttcn // Description: TCC Useful Functions: Generic Types For Maths -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2007-11-12 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCMessageHandling.cc b/src/TCCMessageHandling.cc index ad11881..07893e7 100644 --- a/src/TCCMessageHandling.cc +++ b/src/TCCMessageHandling.cc @@ -1,18 +1,16 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2013 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCMessageHandling.cc -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2013-11-07 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCMessageHandling_Functions.ttcn b/src/TCCMessageHandling_Functions.ttcn index cc84f67..6d2b3f9 100644 --- a/src/TCCMessageHandling_Functions.ttcn +++ b/src/TCCMessageHandling_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2013 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCMessageHandling_Functions.ttcn // Description: TCC Useful Functions: MessageHandling Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2013-03-28 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCOpenSecurity.cc b/src/TCCOpenSecurity.cc new file mode 100644 index 0000000..527faee --- /dev/null +++ b/src/TCCOpenSecurity.cc @@ -0,0 +1,1128 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +// +// File: TCCOpenSecurity.cc +// Description: TCC Useful Functions: Security Functions +// Rev: R30A +// Prodnr: CNL 113 472 +// +/////////////////////////////////////////////////////////////////////////////// +#include "TCCOpenSecurity_Functions.hh" + +#include <openssl/md5.h> +#include <openssl/hmac.h> +#include <openssl/aes.h> +#include <openssl/des.h> +#include <openssl/evp.h> +#include <openssl/dh.h> +#include <openssl/sha.h> +#include <openssl/rand.h> + +namespace TCCOpenSecurity__Functions { + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f__calculateRAND__oct +// +// Purpose: +// Compute random value +// +// Parameters: +// pl__length - *in* *integer* - length of random value +// +// Return Value: +// random value - *out* *octetstring* - random value +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING f__calculateRAND__oct(const INTEGER& pl__length) +{ + int rand_length = (int)pl__length; + unsigned char rand_val[rand_length]; + RAND_bytes(rand_val, rand_length); + + return OCTETSTRING(rand_length, rand_val); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f__calculateSHA1 +// +// Purpose: +// Compute SHA1 hash value +// +// Parameters: +// pszHashInput - *in* *charstring* - input value to compute hash of +// +// Return Value: +// hashValue - *out* *charstring* - hexa hash value of input +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +CHARSTRING f__calculateSHA1(const CHARSTRING& pszHashInput) +{ + unsigned char sha1[SHA_DIGEST_LENGTH]; + SHA1((const unsigned char*)(const char *)pszHashInput,pszHashInput.lengthof(),sha1); + + return oct2str(OCTETSTRING(SHA_DIGEST_LENGTH,sha1)); +} + +/////////////////////////////////////////////////////////////////////////////// +// Function: f__calculateSHA1__oct +// +// Purpose: +// Compute SHA1 hash value and return in octetstring +// +// Parameters: +// pszHashInput - *in* *octetstring* - input value to compute hash of +// +// Return Value: +// hashValue - *out* *octetstring* - hash value of input in octetstring +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING f__calculateSHA1__oct(const OCTETSTRING& pszHashInput) +{ + unsigned char sha1[SHA_DIGEST_LENGTH]; + SHA1((const unsigned char*)pszHashInput,pszHashInput.lengthof(),sha1); + + return OCTETSTRING(SHA_DIGEST_LENGTH,sha1); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f__calculateHMACMD5 +// +// Purpose: +// Calculate the HMAC MD5 value of a message with specified 64 bit key. +// +// Parameters: +// msg - *in* *octetstring* - message to be hashed +// key - *in* *OCT_64* - 64 bit key of the hash function +// +// Return Value: +// octetstring - Hash value (16 octet - 128 bit) +// +// Errors: +// - +// +// Detailed description: +// - (should be kept because of backward compatibility reasons) +// - HMAC() is an openssl specific function, should be found under openssl/hmac.h +// - key can only be 64 bit (any other case please use f_calculate_HMAC_MD5) +// - the length of generated hash value can only be 128 bit (any other case please use f_calculate_HMAC_MD5) +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING f__calculateHMACMD5(const OCTETSTRING& msg, const OCT__64& key) +{ + unsigned char Response[16]; + int msglen = msg.lengthof(); + + HMAC(EVP_md5(), key, 64, msg, msglen, Response, NULL); + + return OCTETSTRING(16, (const unsigned char *)Response); +} + +/////////////////////////////////////////////////////////////////////////////// +// Function: f__calculate__HMAC__MD5 +// +// Purpose: +// Calculate the HMAC MD5 value of a message with specified key. +// +// Parameters: +// pl_key - *in* *octetstring* - key of the hash function +// pl_input - *in* *octetstring* - message to be hashed +// pl_length - *in* *integer* - length of the output hash value (should be 16 in most of the cases) +// +// Return Value: +// octetstring - Hash value +// +// Errors: +// - +// +// Detailed description: +// - HMAC() is an openssl specific function, should be found under openssl/hmac.h +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING f__calculate__HMAC__MD5(const OCTETSTRING& pl_key,const OCTETSTRING& pl_input,const INTEGER& pl_length) +{ + unsigned int out_length; + unsigned char output[EVP_MAX_MD_SIZE]; + HMAC(EVP_md5(), pl_key, (size_t) pl_key.lengthof(), pl_input, (size_t) pl_input.lengthof(), output, &out_length); + + return OCTETSTRING(pl_length, output); +} + +/////////////////////////////////////////////////////////////////////////////// +// Function: f__calculate__HMAC__SHA1 +// +// Purpose: +// Calculate the HMAC SHA1 value of a message with specified key. +// +// Parameters: +// pl_key - *in* *octetstring* - key of the hash function +// pl_input - *in* *octetstring* - message to be hashed +// pl_length - *in* *integer* - length of the output hash value (should be 16 in most of the cases) +// +// Return Value: +// octetstring - Hash value +// +// Errors: +// - +// +// Detailed description: +// - HMAC() is an openssl specific function, should be found under openssl/hmac.h +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING f__calculate__HMAC__SHA1(const OCTETSTRING& pl_key,const OCTETSTRING& pl_input,const INTEGER& pl_length) +{ + unsigned int out_length; + unsigned char output[EVP_MAX_MD_SIZE]; + HMAC(EVP_sha1(), pl_key, (size_t) pl_key.lengthof(), pl_input, (size_t) pl_input.lengthof(), output, &out_length); + + return OCTETSTRING(pl_length, output); +} + +/////////////////////////////////////////////////////////////////////////////// +// Function: f__calculate__HMAC__SHA256 +// +// Purpose: +// Calculate the HMAC SHA256 value of a message with specified key. +// +// Parameters: +// pl_key - *in* *octetstring* - key of the hash function +// pl_input - *in* *octetstring* - message to be hashed +// pl_length - *in* *integer* - length of the output hash value (should be 32 in most of the cases) +// +// Return Value: +// octetstring - Hash value +// +// Errors: +// - +// +// Detailed description: +// - HMAC() is an openssl specific function, should be found under openssl/hmac.h +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING f__calculate__HMAC__SHA256(const OCTETSTRING& pl_key,const OCTETSTRING& pl_input,const INTEGER& pl_length) +{ + unsigned int out_length; + unsigned char output[EVP_MAX_MD_SIZE]; + HMAC(EVP_sha256(), pl_key, (size_t) pl_key.lengthof(), pl_input, (size_t) pl_input.lengthof(), output, &out_length); + + return OCTETSTRING(pl_length, output); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f__AES__CBC__128__Encrypt__OpenSSL +// +// Purpose: Calculate AES 128 CBC encrypted value +// +// Parameters: +// p__key - *in* *octetstring* - Key +// p__iv - *in* *octetstring* - Initialiazation Vector +// p__data - *in* *octetstring* - Data +// +// Return Value: +// octetstring - encrypted value +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING f__AES__CBC__128__Encrypt__OpenSSL (const OCTETSTRING& p_key,const OCTETSTRING& p_iv,const OCTETSTRING& p_data) +{ + + const unsigned char* key=(const unsigned char*)p_key; + const unsigned char* iv=(const unsigned char*)p_iv; + size_t data_len = p_data.lengthof(); + const unsigned char* data=(const unsigned char*)p_data; + size_t iv_len = p_iv.lengthof(); + + AES_KEY enc_key; + unsigned char enc_data[data_len]; + unsigned char k_iv[iv_len]; + + memcpy(k_iv,iv,iv_len); + + AES_set_encrypt_key(key, 128, &enc_key); + + AES_cbc_encrypt(data, enc_data, + data_len, &enc_key, + k_iv, AES_ENCRYPT); + + return OCTETSTRING(data_len, enc_data); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f__AES__CBC__128__Decrypt__OpenSSL +// +// Purpose: Dectrypts AES 128 CBC encrypted data +// +// Parameters: +// p__key - *in* *octetstring* - Key +// p__iv - *in* *octetstring* - Initialiazation Vector +// p__data - *in* *octetstring* - Encrypted Value +// +// Return Value: +// octetstring - decrypted original data +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING f__AES__CBC__128__Decrypt__OpenSSL (const OCTETSTRING& p_key,const OCTETSTRING& p_iv,const OCTETSTRING& p_data) +{ + + const unsigned char* key=(const unsigned char*)p_key; + const unsigned char* iv=(const unsigned char*)p_iv; + size_t data_len = p_data.lengthof(); + const unsigned char* data=(const unsigned char*)p_data; + size_t iv_len = p_iv.lengthof(); + + AES_KEY dec_key; + unsigned char dec_data[data_len]; + unsigned char k_iv[iv_len]; + + memcpy(k_iv,iv,iv_len); + + AES_set_decrypt_key(key, 128, &dec_key); + + AES_cbc_encrypt(data, dec_data, + data_len, &dec_key, + k_iv, AES_DECRYPT); + + return OCTETSTRING(data_len, dec_data); +} + +/////////////////////////////////////////////////////////////////////////////// +// Function: f__AES__CBC__Encrypt__OpenSSL +// +// Purpose: Calculate AES 128 CBC encrypted value with arbitrary key length +// +// Parameters: +// p__key - *in* *octetstring* - Key +// p__iv - *in* *octetstring* - Initialiazation Vector +// p__data - *in* *octetstring* - Data +// +// Return Value: +// octetstring - encrypted value +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING f__AES__CBC__Encrypt__OpenSSL (const OCTETSTRING& p_key,const OCTETSTRING& p_iv,const OCTETSTRING& p_data) +{ + const unsigned char* key=(const unsigned char*)p_key; + const int key_len_bit = p_key.lengthof() * 8; + const unsigned char* iv=(const unsigned char*)p_iv; + size_t data_len = p_data.lengthof(); + const unsigned char* data=(const unsigned char*)p_data; + size_t iv_len = p_iv.lengthof(); + + AES_KEY enc_key; + unsigned char enc_data[data_len]; + unsigned char k_iv[iv_len]; + + memcpy(k_iv,iv,iv_len); + + AES_set_encrypt_key(key, key_len_bit, &enc_key); + + AES_cbc_encrypt(data, enc_data, + data_len, &enc_key, + k_iv, AES_ENCRYPT); + + return OCTETSTRING(data_len, enc_data); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f__AES__CBC__Decrypt__OpenSSL +// +// Purpose: Dectrypts AES CBC encrypted data with arbitrary key length +// +// Parameters: +// p__key - *in* *octetstring* - Key +// p__iv - *in* *octetstring* - Initialiazation Vector +// p__data - *in* *octetstring* - Encrypted Value +// +// Return Value: +// octetstring - decrypted original data +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING f__AES__CBC__Decrypt__OpenSSL (const OCTETSTRING& p_key,const OCTETSTRING& p_iv,const OCTETSTRING& p_data) +{ + + const unsigned char* key=(const unsigned char*)p_key; + const int key_len_bit = p_key.lengthof() * 8; + const unsigned char* iv=(const unsigned char*)p_iv; + size_t data_len = p_data.lengthof(); + const unsigned char* data=(const unsigned char*)p_data; + size_t iv_len = p_iv.lengthof(); + + AES_KEY dec_key; + unsigned char dec_data[data_len]; + unsigned char k_iv[iv_len]; + + memcpy(k_iv,iv,iv_len); + + AES_set_decrypt_key(key, key_len_bit, &dec_key); + + AES_cbc_encrypt(data, dec_data, + data_len, &dec_key, + k_iv, AES_DECRYPT); + + return OCTETSTRING(data_len, dec_data); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef__3DES__ECB__Encrypt +// +// Purpose: Encrypts data using 3DES algorithm in ECB mode. +// +// Parameters: +// pl__data - *in* *octetstring* - Data to be encrypted +// pl__key - *in* *octetstring* - Key +// +// Return Value: +// octetstring - encrypted data +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING ef__3DES__ECB__Encrypt (const OCTETSTRING& pl__data, const OCTETSTRING& pl__key, const BOOLEAN& pl__use__padding) +{ + if(pl__data.lengthof()==0){ + return OCTETSTRING(0,NULL); + } + + int outl = 0; + int position = 0; + OCTETSTRING ret_val=OCTETSTRING(0,NULL); + unsigned char* outbuf=NULL; + const unsigned char* data= (const unsigned char*)pl__data; + + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + + if(EVP_EncryptInit_ex(&ctx, EVP_des_ede3_ecb(), NULL, pl__key, NULL)) + { + int block_size = EVP_CIPHER_CTX_block_size(&ctx); + if(!pl__use__padding) { // the padding is used by default + EVP_CIPHER_CTX_set_padding(&ctx,0); + if(pl__data.lengthof()%block_size){ + TTCN_warning("ef_3DES_ECB_Encrypt: The length of the pl_data should be n * %d (the block size) if padding is not used.", block_size); + EVP_CIPHER_CTX_cleanup(&ctx); + return OCTETSTRING(0,NULL); + } + } + if((outbuf = (unsigned char*)Malloc(pl__data.lengthof() + block_size)) != NULL) + { + if(!EVP_EncryptUpdate(&ctx, outbuf, &outl, data, pl__data.lengthof())){ + TTCN_warning("ef_3DES_ECB_Encrypt: EVP_EncryptUpdate failed."); + Free(outbuf); + EVP_CIPHER_CTX_cleanup(&ctx); + return OCTETSTRING(0,NULL); + } + position = outl; + if(!EVP_EncryptFinal_ex(&ctx, &outbuf[position], &outl)){ + TTCN_warning("ef_3DES_ECB_Encrypt: EVP_EncryptFinal_ex failed."); + Free(outbuf); + EVP_CIPHER_CTX_cleanup(&ctx); + return OCTETSTRING(0,NULL); + } + + position += outl; + ret_val=OCTETSTRING(position, outbuf); + Free(outbuf); + } + + EVP_CIPHER_CTX_cleanup(&ctx); + + } else { + TTCN_warning("ef_3DES_ECB_Encrypt: EVP_EncryptInit_ex failed."); + return OCTETSTRING(0,NULL); + } + + + return ret_val; + +} + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef__3DES__ECB__Decrypt +// +// Purpose: Dectrypts 3DES ECB encrypted data. +// +// Parameters: +// pl__data - *in* *octetstring* - Encrytped data +// pl__key - *in* *octetstring* - Key +// +// Return Value: +// octetstring - decrypted data +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING ef__3DES__ECB__Decrypt (const OCTETSTRING& pl__data, const OCTETSTRING& pl__key, const BOOLEAN& pl__use__padding) +{ + if(pl__data.lengthof()==0){ + return OCTETSTRING(0,NULL); + } + int outl = 0; + int position = 0; + OCTETSTRING ret_val=OCTETSTRING(0,NULL); + unsigned char* outbuf=NULL; + const unsigned char* data= (const unsigned char*)pl__data; + + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + + if(EVP_DecryptInit_ex(&ctx, EVP_des_ede3_ecb(), NULL, pl__key, NULL)) + { + int block_size = EVP_CIPHER_CTX_block_size(&ctx); + if(pl__data.lengthof()%block_size){ + TTCN_warning("ef_3DES_ECB_Decrypt: The length of the pl_data should be n * %d (the block size)!", block_size); + EVP_CIPHER_CTX_cleanup(&ctx); + return OCTETSTRING(0,NULL); + } + if(!pl__use__padding) { // the padding is used by default + EVP_CIPHER_CTX_set_padding(&ctx,0); + } + if((outbuf = (unsigned char*)Malloc(pl__data.lengthof() + block_size)) != NULL) + { + if(!EVP_DecryptUpdate(&ctx, outbuf, &outl, data, pl__data.lengthof())){ + TTCN_warning("ef_3DES_ECB_Decrypt: EVP_DecryptUpdate failed."); + Free(outbuf); + EVP_CIPHER_CTX_cleanup(&ctx); + return OCTETSTRING(0,NULL); + } + position = outl; + + if(!EVP_DecryptFinal_ex(&ctx, &outbuf[position], &outl)){ + TTCN_warning("ef_3DES_ECB_Decrypt: EVP_DecryptFinal_ex failed."); + Free(outbuf); + EVP_CIPHER_CTX_cleanup(&ctx); + return OCTETSTRING(0,NULL); + } + + position += outl; + ret_val=OCTETSTRING(position, outbuf); + Free(outbuf); + } + + EVP_CIPHER_CTX_cleanup(&ctx); + + } else { + TTCN_warning("ef_3DES_ECB_Decrypt: EVP_DecryptInit_ex failed."); + return OCTETSTRING(0,NULL); + } + + + return ret_val; + +} + + + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef__3DES__CBC__Encrypt +// +// Purpose: Encrypts data using TripleDES algorithm in CBC mode. +// +// Parameters: +// pl__data - *in* *octetstring* - Data to be encrypted +// pl__key - *in* *octetstring* - Key +// pl__iv - *in* *octetstring* - Initialiazation Vector +// +// Return Value: +// octetstring - decrypted original data +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING ef__3DES__CBC__Encrypt (const OCTETSTRING& pl__data, const OCTETSTRING& pl__key, const OCTETSTRING& pl__iv, const BOOLEAN& pl__use__padding) +{ + if(pl__data.lengthof()==0){ + return OCTETSTRING(0,NULL); + } + int outl = 0; + int position = 0; + OCTETSTRING ret_val=OCTETSTRING(0,NULL); + unsigned char* outbuf=NULL; + const unsigned char* data= (const unsigned char*)pl__data; + + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + + if(EVP_EncryptInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, pl__key, pl__iv)) + { + int block_size = EVP_CIPHER_CTX_block_size(&ctx); + if(!pl__use__padding) { // the padding is used by default + EVP_CIPHER_CTX_set_padding(&ctx,0); + if(pl__data.lengthof()%block_size){ + TTCN_warning("ef_3DES_CBC_Encrypt: The length of the pl_data should be n * %d (the block size) if padding is not used.", block_size); + EVP_CIPHER_CTX_cleanup(&ctx); + return OCTETSTRING(0,NULL); + } + } + if((outbuf = (unsigned char*)Malloc(pl__data.lengthof() + block_size)) != NULL) + { + if(!EVP_EncryptUpdate(&ctx, outbuf, &outl, data, pl__data.lengthof())){ + TTCN_warning("ef_3DES_CBC_Encrypt: EVP_EncryptUpdate failed."); + Free(outbuf); + EVP_CIPHER_CTX_cleanup(&ctx); + return OCTETSTRING(0,NULL); + } + + position = outl; + + if(!EVP_EncryptFinal_ex(&ctx, &outbuf[position], &outl)){ + TTCN_warning("ef_3DES_CBC_Encrypt: EVP_EncryptFinal_ex failed."); + Free(outbuf); + EVP_CIPHER_CTX_cleanup(&ctx); + return OCTETSTRING(0,NULL); + } + + position += outl; + } + + ret_val=OCTETSTRING(position, outbuf); + Free(outbuf); + EVP_CIPHER_CTX_cleanup(&ctx); + + } else { + TTCN_warning("ef_3DES_CBC_Encrypt: EVP_EncryptInit_ex failed."); + return OCTETSTRING(0,NULL); + } + + + return ret_val; + +} + +/////////////////////////////////////////////////////////////////////////////// +// Function: f__3DES__CBC__Decrypt +// +// Purpose: Decrypting TripleDES encypted data. +// +// Parameters: +// pl__data - *in* *octetstring* - Encrypted Value +// pl__key - *in* *octetstring* - Key +// pl__iv - *in* *octetstring* - Initialiazation Vector +// +// Return Value: +// octetstring - encrypted value +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING ef__3DES__CBC__Decrypt (const OCTETSTRING& pl__data, const OCTETSTRING& pl__key, const OCTETSTRING& pl__iv, const BOOLEAN& pl__use__padding) +{ + if(pl__data.lengthof()==0){ + return OCTETSTRING(0,NULL); + } + int outl = 0; + int position = 0; + OCTETSTRING ret_val=OCTETSTRING(0,NULL); + unsigned char* outbuf=NULL; + const unsigned char* data= (const unsigned char*)pl__data; + + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + + if(EVP_DecryptInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, pl__key, pl__iv)) + { + int block_size = EVP_CIPHER_CTX_block_size(&ctx); + if(pl__data.lengthof()%block_size){ + TTCN_warning("ef__3DES__CBC__Decrypt: The length of the pl_data should be n * %d (the block size)!", block_size); + EVP_CIPHER_CTX_cleanup(&ctx); + return OCTETSTRING(0,NULL); + } + if(!pl__use__padding) { // the padding is used by default + EVP_CIPHER_CTX_set_padding(&ctx,0); + } + if((outbuf = (unsigned char*)Malloc(pl__data.lengthof() + block_size)) != NULL) + { + if(!EVP_DecryptUpdate(&ctx, outbuf, &outl, data, pl__data.lengthof())){ + TTCN_warning("ef_3DES_CBC_Decrypt: EVP_DecryptUpdate failed."); + Free(outbuf); + EVP_CIPHER_CTX_cleanup(&ctx); + return OCTETSTRING(0,NULL); + } +; + position = outl; + + if(!EVP_DecryptFinal_ex(&ctx, &outbuf[position], &outl)){ + TTCN_warning("ef_3DES_ECB_Decrypt: EVP_DecryptFinal_ex failed."); + Free(outbuf); + EVP_CIPHER_CTX_cleanup(&ctx); + return OCTETSTRING(0,NULL); + } + position += outl; + ret_val=OCTETSTRING(position, outbuf); + Free(outbuf); + } + + EVP_CIPHER_CTX_cleanup(&ctx); + + } else { + TTCN_warning("ef_3DES_CBC_Decrypt: EVP_DecryptInit_ex failed."); + return OCTETSTRING(0,NULL); + } + + + return ret_val; + +} + + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef_Calculate__AES__XCBC__128 +// +// Purpose: Calculates the AES XCBC value of the data with a 128 bit key. +// +// Parameters: +// pl__data - *in* *octetstring* - Data +// pl__key - *in* *octetstring* - Key +// pl__out__length - *in* *integer* - Length of the output +// +// Return Value: +// octetstring - AES XCBC value +// +// Errors: +// - +// +// Detailed description: +// AES XCBC generates a 16 byte long value which can be truncated +// to a length given in pl__out__length. +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING ef__Calculate__AES__XCBC__128 (const OCTETSTRING& pl__data, const OCTETSTRING& pl__key, const INTEGER& pl__out__length) +{ + const int data_length = pl__data.lengthof(); + const unsigned char* data = (const unsigned char*)pl__data; + const int block_size = 16; + int outl; + + unsigned char key1[block_size] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; + unsigned char key2[block_size] = { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }; + unsigned char key3[block_size] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; + unsigned char e[block_size] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX_init(&ctx); + + EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, pl__key, NULL); + EVP_EncryptUpdate(&ctx, key1, &outl, key1, block_size); + EVP_CIPHER_CTX_cleanup(&ctx); + + EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, pl__key, NULL); + EVP_EncryptUpdate(&ctx, key2, &outl, key2, block_size); + EVP_CIPHER_CTX_cleanup(&ctx); + + EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, pl__key, NULL); + EVP_EncryptUpdate(&ctx, key3, &outl, key3, block_size); + EVP_CIPHER_CTX_cleanup(&ctx); + + if(EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key1, NULL)) + { + for(int i = 0; i < data_length - block_size; i += block_size) + { + for(int j = 0; j < block_size; j++) + { + e[j] ^= data[i+j]; + } + + EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key1, NULL); + EVP_EncryptUpdate(&ctx, e, &outl, e, block_size); + EVP_CIPHER_CTX_cleanup(&ctx); + } + + int last_block_length = data_length % block_size; + + if((last_block_length == 0) && (data_length != 0)) + { + for(int i = 0; i < block_size; i++) + { + e[i] = data[data_length - block_size + i] ^ e[i] ^ key2[i]; + } + } else { + int i = 0; + + while(i < last_block_length) + { + e[i] = data[data_length - last_block_length + i] ^ e[i] ^ key3[i]; + i++; + } + + e[i] = 0x80 ^ e[i] ^ key3[i]; + i++; + + + while(i < block_size) + { + e[i] ^= key3[i]; + i++; + } + + } + EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key1, NULL); + EVP_EncryptUpdate(&ctx, e, &outl, e, block_size); + EVP_CIPHER_CTX_cleanup(&ctx); + + return OCTETSTRING(pl__out__length, (const unsigned char*)e); + + } + return OCTETSTRING(0,NULL); +} + + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef_DH_generate_private_public_keys +// +// Purpose: Generates public and private keys (this party). +// +// Parameters: +// pl__keyLength - *in* *integer* - Key length (bytes) +// pl__pubkey - *inout* *octetstring* - Public key (other party) +// pl__privkey - *inout* *octetstring* - Private key (this party) +// +// Return Value: +// octetstring - DH shared secret +// +// Errors: +// - +// +// Detailed description: +// Computes the shared secret from the originating side's private key and +// the public key of the responding side as described in DH group 1, 2 and 14. +// Keys must be either 96, 128 or 256 bytes long. +// +/////////////////////////////////////////////////////////////////////////////// +INTEGER ef__DH__generate__private__public__keys (const INTEGER& pl__keyLength, OCTETSTRING& pl__pubkey, OCTETSTRING& pl__privkey) +{ + int key_length = (int)pl__keyLength; + + const char* prime_768 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"; + + const char* prime_1024 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"; + + const char* prime_2048 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF"; + + DH* dh = DH_new(); + + BIGNUM* prime = BN_new(); + switch(key_length) + { + case 96: BN_hex2bn(&prime, prime_768); break; + case 128: BN_hex2bn(&prime, prime_1024); break; + case 256: BN_hex2bn(&prime, prime_2048); break; + default: + { + DH_free(dh); + return INTEGER(0); + } + } + dh->p = prime; + + const char* generator = "2"; + BIGNUM* gen = BN_new(); + BN_hex2bn(&gen, generator); + dh->g = gen; + + DH_generate_key(dh); + + int pub_len = BN_num_bytes(dh->pub_key); + unsigned char* pub_key = (unsigned char*)Malloc(pub_len * sizeof(unsigned char)); + pub_len = BN_bn2bin(dh->pub_key, pub_key); + if (key_length-pub_len > 0) + {pl__pubkey = int2oct(0,key_length-pub_len) + OCTETSTRING(pub_len, pub_key);} + else + {pl__pubkey = OCTETSTRING(key_length, pub_key);} + Free(pub_key); + + if (pub_len <= 0) + { + DH_free(dh); + return INTEGER(0); + } + + int priv_len = BN_num_bytes(dh->priv_key); + unsigned char* priv_key = (unsigned char*)Malloc(priv_len * sizeof(unsigned char)); + priv_len = BN_bn2bin(dh->priv_key, priv_key); + if (key_length-priv_len > 0) + {pl__privkey = int2oct(0,key_length-priv_len) + OCTETSTRING(priv_len, priv_key);} + else + {pl__privkey = OCTETSTRING(key_length, priv_key);} + Free(priv_key); + + if (priv_len <= 0) + { + DH_free(dh); + return INTEGER(0); + } + + DH_free(dh); + return INTEGER(1); +} + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef_DH_shared_secret +// +// Purpose: Calculates the shared secret from the given public and private keys. +// +// Parameters: +// pl__pubkey - *in* *octetstring* - Public key (other party) +// pl__privkey - *in* *octetstring* - Private key (this party) +// +// Return Value: +// octetstring - DH shared secret +// +// Errors: +// - +// +// Detailed description: +// Computes the shared secret from the originating side's private key and +// the public key of the responding side as described in DH group 1, 2 and 14. +// Keys must be either 96, 128 or 256 bytes long. +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING ef__DH__shared__secret (const OCTETSTRING& pl__pubkey, const OCTETSTRING& pl__privkey) +{ + int key_length = pl__pubkey.lengthof(); + unsigned char shared_secret[key_length]; + + const char* prime_768 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"; + + const char* prime_1024 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"; + + const char* prime_2048 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF"; + + DH* dh = DH_new(); + + BIGNUM* prime = BN_new(); + switch(key_length) + { + case 96: BN_hex2bn(&prime, prime_768); break; + case 128: BN_hex2bn(&prime, prime_1024); break; + case 256: BN_hex2bn(&prime, prime_2048); break; + default: + { + DH_free(dh); + return OCTETSTRING(0, NULL); + } + } + dh->p = prime; + + const char* generator = "2"; + BIGNUM* gen = BN_new(); + BN_hex2bn(&gen, generator); + dh->g = gen; + + BIGNUM* priv_key = BN_new(); + BN_bin2bn((const unsigned char*)pl__privkey, key_length, priv_key); + dh->priv_key = priv_key; + + BIGNUM* pub_key = BN_new(); + BN_bin2bn((const unsigned char*)pl__pubkey, key_length, pub_key); + dh->pub_key = pub_key; + + if(DH_compute_key(shared_secret, pub_key, dh)) + { + DH_free(dh); + return OCTETSTRING(key_length, shared_secret); + } + + DH_free(dh); + return OCTETSTRING(0, NULL); + +} + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_AES_ECB_128_Encrypt_OpenSSL +// +// Purpose: Calculate AES 128 ECB encrypted value +// +// Parameters: +// p_key - *in* *octetstring* - Key +// p_data - *in* *octetstring* - Data +// +// Return Value: +// octetstring - encrypted value +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING f__AES__ECB__128__Encrypt__OpenSSL (const OCTETSTRING& p_key,const OCTETSTRING& p_data) +{ + if(p_key.lengthof()!=16){ + TTCN_error("f_AES_EBC_128_Encrypt_OpenSSL: The length of the key should be 16 instead of %d",p_key.lengthof() ); + } + const unsigned char* data=(const unsigned char*)p_data; + int data_len = p_data.lengthof(); + + int outbuf_len=data_len+AES_BLOCK_SIZE; + + unsigned char* outbuf=(unsigned char*)Malloc(outbuf_len * sizeof(unsigned char)); + + int round=((data_len+AES_BLOCK_SIZE-1)/AES_BLOCK_SIZE)*AES_BLOCK_SIZE; + + AES_KEY aes_k; + AES_set_encrypt_key((const unsigned char*)p_key,128,&aes_k); + + for(int i=0;i<round; i++){ + if((i+1)*AES_BLOCK_SIZE > data_len){ // last partial block + unsigned char b[AES_BLOCK_SIZE]; + memset(b,0,AES_BLOCK_SIZE); + memcpy(b,data+(i*AES_BLOCK_SIZE),data_len-(i*AES_BLOCK_SIZE)); + AES_encrypt(data+(i*AES_BLOCK_SIZE),outbuf+(i*AES_BLOCK_SIZE),&aes_k); + } else { // full block + AES_encrypt(data+(i*AES_BLOCK_SIZE),outbuf+(i*AES_BLOCK_SIZE),&aes_k); + } + } + + + OCTETSTRING ret_val=OCTETSTRING(data_len,outbuf ); + return ret_val; +} + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_AES_ECB_128_Decrypt_OpenSSL +// +// Purpose: Calculate AES 128 ECB decrypted value +// +// Parameters: +// p_key - *in* *octetstring* - Key +// p_data - *in* *octetstring* - Data +// +// Return Value: +// octetstring - encrypted value +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +OCTETSTRING f__AES__ECB__128__Decrypt__OpenSSL (const OCTETSTRING& p_key,const OCTETSTRING& p_data) +{ + if(p_key.lengthof()!=16){ + TTCN_error("f_AES_EBC_128_Decrypt_OpenSSL: The length of the key should be 16 instead of %d",p_key.lengthof() ); + } + const unsigned char* data=(const unsigned char*)p_data; + int data_len = p_data.lengthof(); + + int outbuf_len=data_len+AES_BLOCK_SIZE; + + unsigned char* outbuf=(unsigned char*)Malloc(outbuf_len * sizeof(unsigned char)); + + int round=((data_len+AES_BLOCK_SIZE-1)/AES_BLOCK_SIZE)*AES_BLOCK_SIZE; + + AES_KEY aes_k; + AES_set_decrypt_key((const unsigned char*)p_key,128,&aes_k); + + for(int i=0;i<round; i++){ + if((i+1)*AES_BLOCK_SIZE > data_len){ // last partial block + unsigned char b[AES_BLOCK_SIZE]; + memset(b,0,AES_BLOCK_SIZE); + memcpy(b,data+(i*AES_BLOCK_SIZE),data_len-(i*AES_BLOCK_SIZE)); + AES_decrypt(data+(i*AES_BLOCK_SIZE),outbuf+(i*AES_BLOCK_SIZE),&aes_k); + } else { // full block + AES_decrypt(data+(i*AES_BLOCK_SIZE),outbuf+(i*AES_BLOCK_SIZE),&aes_k); + } + } + + + OCTETSTRING ret_val=OCTETSTRING(data_len,outbuf ); + return ret_val; +} +OCTETSTRING f__AES__CTR__128__Encrypt__Decrypt__OpenSSL (const OCTETSTRING& p_key,const OCTETSTRING& p_iv,const OCTETSTRING& p_data) +{ + if(p_key.lengthof()!=16){ + TTCN_error("f_AES_EBC_128_Decrypt_OpenSSL: The length of the key should be 16 instead of %d",p_key.lengthof() ); + } + if(p_iv.lengthof()!=16){ + TTCN_error("f_AES_EBC_128_Decrypt_OpenSSL: The length of the IV should be 16 instead of %d",p_iv.lengthof() ); + } + AES_KEY aes_k; + AES_set_encrypt_key((const unsigned char*)p_key,128,&aes_k); + + int data_len=p_data.lengthof(); + unsigned char enc_data[data_len]; + unsigned char k_iv[AES_BLOCK_SIZE]; + memcpy(k_iv,(const unsigned char*)p_iv,AES_BLOCK_SIZE); + + unsigned int num = 0; + unsigned char ecount_buf[AES_BLOCK_SIZE]; + memset(ecount_buf, 0, AES_BLOCK_SIZE); + + AES_ctr128_encrypt((const unsigned char*)p_data, enc_data, data_len, &aes_k, k_iv, ecount_buf, &num); + + return OCTETSTRING(data_len, enc_data); +} + +} diff --git a/src/TCCOpenSecurity_Functions.ttcn b/src/TCCOpenSecurity_Functions.ttcn new file mode 100644 index 0000000..8152cf6 --- /dev/null +++ b/src/TCCOpenSecurity_Functions.ttcn @@ -0,0 +1,585 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html +/////////////////////////////////////////////////////////////////////////////// +// +// File: TCCOpenSecurity.ttcn +// Description: TCC Useful Functions: Security Functions +// Rev: R30A +// Prodnr: CNL 113 472 +// +/////////////////////////////////////////////////////////////////////////////// + +module TCCOpenSecurity_Functions { + +type octetstring OCT_16 length(16); +type octetstring OCT_64 length(64); + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_calculateRAND_oct +// +// Purpose: +// Compute random value +// +// Parameters: +// pl_length - *in* *integer* - length of random value +// +// Return Value: +// random value - *out* *octetstring* - random value +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function f_calculateRAND_oct(in integer pl_length) return octetstring; + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_calculateSHA1 +// +// Purpose: +// Compute SHA1 hash value +// +// Parameters: +// pszHashInput - *in* *charstring* - input value to compute SHA1 hash +// +// Return Value: +// charstring - hexa hash value of input +// +// Errors: +// - +// +// Detailed description: +// - SHA1() is an openssl specific function, should be found under openssl/sha.h +// +/////////////////////////////////////////////////////////////////////////////// +external function f_calculateSHA1(in charstring pszHashInput) return charstring; + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_calculateSHA1_oct +// +// Purpose: +// Compute SHA1 hash value, octetstring output +// +// Parameters: +// pszHashInput - *in* *charstring* - input value to compute SHA1 hash +// +// Return Value: +// octetstring - octetstring hash value of input +// +// Errors: +// - +// +// Detailed description: +// - SHA1() is an openssl specific function, should be found under openssl/sha.h +// +/////////////////////////////////////////////////////////////////////////////// +external function f_calculateSHA1_oct(in octetstring pszHashInput) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_calculateHMACMD5 +// +// Purpose: +// Calculate the 128 bit HMAC MD5 value of a message with specified 64 bit key. +// +// Parameters: +// msg - *in* *octetstring* - message to be hashed +// key - *in* *OCT_64* - 64 bit key of the hash function +// +// Return Value: +// octetstring - Hash value (16 octet) +// +// Errors: +// - +// +// Detailed description: +// - key should be 64 bit long, output is 128 bit long +// +/////////////////////////////////////////////////////////////////////////////// +external function f_calculateHMACMD5(in octetstring msg, in OCT_64 key) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_calculate_HMAC_MD5 +// +// Purpose: +// Calculate the HMAC MD5 value of a message with specified key. +// +// Parameters: +// pl_key - *in* *octetstring* - key of the hash function +// pl_input - *in* *octetstring* - message to be hashed +// pl_length - *in* *integer* - length of the output hash value (should be 16 in most of the cases) +// +// Return Value: +// octetstring - Hash value +// +// Errors: +// - +// +// Detailed description: +// - key can be any length +// - the length of output can be set in pl_length +// +/////////////////////////////////////////////////////////////////////////////// +external function f_calculate_HMAC_MD5(in octetstring pl_key, in octetstring pl_input, in integer pl_length) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_calculate_HMAC_SHA1 +// +// Purpose: +// Calculate the HMAC SHA1 value of a message with specified key. +// +// Parameters: +// pl_key - *in* *octetstring* - key of the hash function +// pl_input - *in* *octetstring* - message to be hashed +// pl_length - *in* *integer* - length of the output hash value (should be 16 in most of the cases) +// +// Return Value: +// octetstring - Hash value +// +// Errors: +// - +// +// Detailed description: +// - key can be any length +// - the length of output can be set in pl_length +// +/////////////////////////////////////////////////////////////////////////////// +external function f_calculate_HMAC_SHA1(in octetstring pl_key, in octetstring pl_input, in integer pl_length) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_calculate_HMAC_SHA256 +// +// Purpose: +// Calculate the HMAC SHA256 value of a message with specified key. +// +// Parameters: +// pl_key - *in* *octetstring* - key of the hash function +// pl_input - *in* *octetstring* - message to be hashed +// pl_length - *in* *integer* - length of the output hash value (should be 32 in most of the cases) +// +// Return Value: +// octetstring - Hash value +// +// Errors: +// - +// +// Detailed description: +// - key can be any length +// - the length of output can be set in pl_length +// +/////////////////////////////////////////////////////////////////////////////// +external function f_calculate_HMAC_SHA256(in octetstring pl_key, in octetstring pl_input, in integer pl_length) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_AES_CBC_128_Encrypt_OpenSSL +// +// Purpose: Calculate AES 128 CBC encrypted value +// +// Parameters: +// p_key - *in* *octetstring* - Key +// p_iv - *in* *octetstring* - Initialiazation Vector +// p_data - *in* *octetstring* - Data +// +// Return Value: +// octetstring - encrypted value +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function f_AES_CBC_128_Encrypt_OpenSSL +( + in octetstring p_key, + in octetstring p_iv, + in octetstring p_data +) return octetstring; + + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_AES_CBC_128_Decrypt_OpenSSL +// +// Purpose: Dectrypts AES 128 CBC encrypted data +// +// Parameters: +// p_key - *in* *octetstring* - Key +// p_iv - *in* *octetstring* - Initialiazation Vector +// p_data - *in* *octetstring* - Encrypted Value +// +// Return Value: +// octetstring - decrypted original data +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function f_AES_CBC_128_Decrypt_OpenSSL +( + in octetstring p_key, + in octetstring p_iv, + in octetstring p_data +) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_AES_CBC_Encrypt_OpenSSL +// +// Purpose: Calculate AES 128 CBC encrypted value with arbitrary key length +// +// Parameters: +// p_key - *in* *octetstring* - Key +// p_iv - *in* *octetstring* - Initialiazation Vector +// p_data - *in* *octetstring* - Data +// +// Return Value: +// octetstring - encrypted value +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function f_AES_CBC_Encrypt_OpenSSL +( + in octetstring p_key, + in octetstring p_iv, + in octetstring p_data +) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_AES_CBC_Decrypt_OpenSSL +// +// Purpose: Dectrypts AES CBC encrypted data with arbitrary key length +// +// Parameters: +// p_key - *in* *octetstring* - Key +// p_iv - *in* *octetstring* - Initialiazation Vector +// p_data - *in* *octetstring* - Encrypted Value +// +// Return Value: +// octetstring - decrypted original data +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function f_AES_CBC_Decrypt_OpenSSL +( + in octetstring p_key, + in octetstring p_iv, + in octetstring p_data +) return octetstring; + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef_3DES_ECB_Encrypt +// +// Purpose: Encrypts data using 3DES algorithm in ECB mode. +// +// Parameters: +// pl_data - *in* *octetstring* - Data to be encrypted +// pl_key - *in* *octetstring* - Key +// pl_use_padding - *in* *boolean* - control the usage of PKCS padding +// +// Return Value: +// octetstring - encrypted data +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function ef_3DES_ECB_Encrypt +( + in octetstring pl_data, + in octetstring pl_key, + in boolean pl_use_padding:=true + +) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef_3DES_ECB_Decrypt +// +// Purpose: Dectrypts 3DES ECB encrypted data. +// +// Parameters: +// pl_data - *in* *octetstring* - Encrytped data +// pl_key - *in* *octetstring* - Key +// pl_use_padding - *in* *boolean* - control the usage of PKCS padding +// +// Return Value: +// octetstring - decrypted data +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function ef_3DES_ECB_Decrypt +( + in octetstring pl_data, + in octetstring pl_key, + in boolean pl_use_padding:=true +) return octetstring; + + + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef_3DES_CBC_Encrypt +// +// Purpose: Encrypts data using TripleDES algorithm in CBC mode. +// +// Parameters: +// pl_data - *in* *octetstring* - Data to be encrypted +// pl_key - *in* *octetstring* - Key +// pl_iv - *in* *octetstring* - Initialiazation Vector +// pl_use_padding - *in* *boolean* - control the usage of PKCS padding +// +// Return Value: +// octetstring - decrypted original data +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function ef_3DES_CBC_Encrypt +( + in octetstring pl_data, + in octetstring pl_key, + in octetstring pl_iv, + in boolean pl_use_padding:=true + +) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef_3DES_CBC_Decrypt +// +// Purpose: Decrypts TripleDES encrypted data. +// +// Parameters: +// pl_data - *in* *octetstring* - Encrypted Value +// pl_key - *in* *octetstring* - Key +// pl_iv - *in* *octetstring* - Initialiazation Vector +// pl_use_padding - *in* *boolean* - control the usage of PKCS padding +// +// Return Value: +// octetstring - decrypted original data +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function ef_3DES_CBC_Decrypt +( + in octetstring pl_data, + in octetstring pl_key, + in octetstring pl_iv, + in boolean pl_use_padding:=true + +) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef_Calculate_AES_XCBC_128 +// +// Purpose: Calculates the AES XCBC value of the data with a 128 bit key. +// +// Parameters: +// pl_data - *in* *octetstring* - Data +// pl_key - *in* *octetstring* - Key +// pl_out_length - *in* *integer* - Length of the output +// +// Return Value: +// octetstring - AES XCBC value +// +// Errors: +// - +// +// Detailed description: +// AES XCBC generates a 16 byte long value which can be truncated +// to a length given in pl_out_length. +// +/////////////////////////////////////////////////////////////////////////////// +external function ef_Calculate_AES_XCBC_128 +( + in octetstring pl_data, + in octetstring pl_key, + in integer pl_out_length +) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef_DH_generate_private_public_keys +// +// Purpose: Generates public and private keys (this party). +// +// Parameters: +// pl_keyLength - *in* *integer* - Key length (bytes) +// pl_pubkey - *inout* *octetstring* - Public key (other party) +// pl_privkey - *inout* *octetstring* - Private key (this party) +// +// Return Value: +// integer - 0: failure, 1 success +// +// Errors: +// - +// +// Detailed description: +// Computes the shared secret from the originating side's private key and +// the public key of the responding side as described in DH group 2 and 14. +// Keys must be either 96, 128 or 256 bytes long. +// +/////////////////////////////////////////////////////////////////////////////// +external function ef_DH_generate_private_public_keys +( + in integer pl_keyLength, + inout octetstring pl_pubkey, + inout octetstring pl_privkey +) return integer; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: ef_DH_shared_secret +// +// Purpose: Calculates the shared secret from the given public and private keys. +// +// Parameters: +// pl_pubkey - *in* *octetstring* - Public key (other party) +// pl_privkey - *in* *octetstring* - Private key (this party) +// +// Return Value: +// octetstring - DH shared secret +// +// Errors: +// - +// +// Detailed description: +// Computes the shared secret from the originating side's private key and +// the public key of the responding side as described in DH group 1, 2 and 14. +// Keys must be either 96, 128 or 256 bytes long. +// +/////////////////////////////////////////////////////////////////////////////// +external function ef_DH_shared_secret +( + in octetstring pl_pubkey, + in octetstring pl_privkey +) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_AES_ECB_128_Encrypt_OpenSSL +// +// Purpose: Calculate AES 128 ECB encrypted value +// +// Parameters: +// p_key - *in* *octetstring* - Key +// p_data - *in* *octetstring* - Data +// +// Return Value: +// octetstring - encrypted value +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function f_AES_ECB_128_Encrypt_OpenSSL +( + OCT_16 p_key, + octetstring p_data +) return octetstring; + + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_AES_ECB_128_Decrypt_OpenSSL +// +// Purpose: Dectrypts AES 128 EBC encrypted data +// +// Parameters: +// p_key - *in* *octetstring* - Key +// p_data - *in* *octetstring* - Encrypted Value +// +// Return Value: +// octetstring - decrypted original data +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function f_AES_ECB_128_Decrypt_OpenSSL +( + OCT_16 p_key, + octetstring p_data +) return octetstring; + +/////////////////////////////////////////////////////////////////////////////// +// Function: f_AES_CTR_128_Encrypt_Decrypt_OpenSSL +// +// Purpose: Calculate AES 128 CTR encrypted value +// +// Parameters: +// p_key - *in* *octetstring* - Key +// p_iv - *in* *octetstring* - Initialiazation Vector (IV+counter) +// p_data - *in* *octetstring* - Data +// +// Return Value: +// octetstring - encrypted value +// +// Errors: +// - +// +// Detailed description: +// - +// +/////////////////////////////////////////////////////////////////////////////// +external function f_AES_CTR_128_Encrypt_Decrypt_OpenSSL +( + OCT_16 p_key, + OCT_16 p_iv, + octetstring p_data +) return octetstring; + + + +} diff --git a/src/TCCPermutatedParameters_Definitions.ttcn b/src/TCCPermutatedParameters_Definitions.ttcn index 5199ff0..6c81a0f 100644 --- a/src/TCCPermutatedParameters_Definitions.ttcn +++ b/src/TCCPermutatedParameters_Definitions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2013 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCPermutatedParameters_Definitions.ttcn // Description: definitions for permutated params -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2013-05-30 -// Contact: http://ttcn.ericsson.se ////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -159,4 +156,4 @@ type record of PP_ParamSet PP_ParamSetList; // is each CGPN has its own current /////////////////////////////////////////////////////////// type set of PP_SingleParam PP_ParamSet; // ie params belonging to one particular call -} with { extension "version R25A"} +} with { extension "version R30A"} diff --git a/src/TCCPermutatedParameters_Functions.ttcn b/src/TCCPermutatedParameters_Functions.ttcn index 092e4df..a009dec 100644 --- a/src/TCCPermutatedParameters_Functions.ttcn +++ b/src/TCCPermutatedParameters_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2013 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCPermutatedParameters_Functions.ttcn // Description: functions for permutated params -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2013-07-17 -// Contact: http://ttcn.ericsson.se ////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// @@ -908,4 +905,4 @@ public function f_PP_getParamValueFromSet( return vl_ret; } -} with { extension "version R25A"} +} with { extension "version R30A"} diff --git a/src/TCCRegexp.cc b/src/TCCRegexp.cc index 96cae5c..3b70154 100644 --- a/src/TCCRegexp.cc +++ b/src/TCCRegexp.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2009 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCRegexp_Functions.ttcn // Description: TCC Useful Functions: Regexp Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2009-11-20 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// @@ -24,7 +21,7 @@ namespace TCCRegexp__Functions{ CHARSTRING f__pcre__regexp(const CHARSTRING& instr, const CHARSTRING& expression, const INTEGER& groupno ){ - + pcre *re; const char *error_text; int erroroffset; @@ -36,7 +33,7 @@ namespace TCCRegexp__Functions{ } int rc; int max_groupno; - + rc=pcre_fullinfo(re,NULL,PCRE_INFO_CAPTURECOUNT,&max_groupno); if(rc!=0){ TTCN_error("pcre_fullinfo failed. Error code: %d",rc); @@ -44,7 +41,7 @@ namespace TCCRegexp__Functions{ max_groupno=(max_groupno+1)*3; int *ovector = (int*)Malloc(max_groupno*sizeof(int)); rc = pcre_exec(re,NULL,instr,instr.lengthof(),0,0,ovector,max_groupno); - + CHARSTRING ret_val; if(rc<=groupno){ ret_val="";} else if( ovector[groupno*2] == -1 ) { ret_val="";} @@ -57,7 +54,7 @@ namespace TCCRegexp__Functions{ charstring__list f__pcre__regexp__list(const CHARSTRING& instr, const CHARSTRING& expression){ - + pcre *re; const char *error_text; int erroroffset; @@ -69,7 +66,7 @@ namespace TCCRegexp__Functions{ } int rc; int max_groupno; - + rc=pcre_fullinfo(re,NULL,PCRE_INFO_CAPTURECOUNT,&max_groupno); if(rc!=0){ TTCN_error("pcre_fullinfo failed. Error code: %d",rc); @@ -77,7 +74,7 @@ namespace TCCRegexp__Functions{ int ovecsivze=(max_groupno+1)*3; int *ovector = (int*)Malloc(ovecsivze*sizeof(int)); rc = pcre_exec(re,NULL,instr,instr.lengthof(),0,0,ovector,ovecsivze); - + charstring__list ret_val; for(int a=0;a<=max_groupno;a++){ if(rc<=a){ ret_val[a]="";} @@ -90,4 +87,48 @@ namespace TCCRegexp__Functions{ return ret_val; } + t__list__of__charstring__list + f__pcre__regexp__list__all__matches(const CHARSTRING& instr, + const CHARSTRING& expression){ + + pcre *re; + const char *error_text; + int erroroffset; + re = pcre_compile(expression,0,&error_text,&erroroffset,NULL); + if(re == NULL){ + TTCN_error("Compilation of the pcre regexp failled at position %d." + "Reason: \"%s\"",erroroffset,error_text); + return NULL_VALUE; + } + int rc; + int max_groupno; + + rc=pcre_fullinfo(re,NULL,PCRE_INFO_CAPTURECOUNT,&max_groupno); + if(rc!=0){ + TTCN_error("pcre_fullinfo failed. Error code: %d",rc); + } + int ovecsivze=(max_groupno+1)*3; + int *ovector = (int*)Malloc(ovecsivze*sizeof(int)); + int ln = instr.lengthof(); + int offset = 0; + t__list__of__charstring__list ret_val = + t__list__of__charstring__list(null_type()); + + while (offset < ln && + (rc = pcre_exec(re,NULL,instr,ln,offset,0,ovector,ovecsivze)) >= 0) + { + charstring__list match; + for(int a=0;a<=max_groupno;a++){ + if(rc<=a){ match[a]="";} + else if( ovector[a*2] == -1 ) { match[a]="";} + else { + match[a]=substr(instr, ovector[a*2], ovector[(a*2)+1]- ovector[a*2]); + } + } + ret_val[ret_val.size_of()] = match; + offset = ovector[1]; + } + Free(ovector); + return ret_val; + } } diff --git a/src/TCCRegexp_Functions.ttcn b/src/TCCRegexp_Functions.ttcn index 3fa2df0..325b28b 100644 --- a/src/TCCRegexp_Functions.ttcn +++ b/src/TCCRegexp_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2009 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCRegexp_Functions.ttcn // Description: TCC Useful Functions: Regexp Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2009-11-20 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// @@ -105,4 +102,35 @@ module TCCRegexp_Functions{ external function f_pcre_regexp_list(in charstring instr, in charstring expression) return charstring_list; +/////////////////////////////////////////////////////////////////////////////// +// Function: f_pcre_regexp_list_all_matches +// +// Purpose: +// Evaulate a Perl compatible regular expression +// +// Parameters: +// instr - *in* *charstring* - string to be matched +// expression - *in* *charstring* - the pattern +// +// Return Value: +// record of charstring_list - the matched substrings +// +// Errors: +// - +// +// Detailed description: +// This function returns the full list of the substring of the input +// character string instr, which is the content of n-th group matching +// to the expression. The expression is a Perl compatible regular expression +// pattern. Group numbers are assigned by the order of occurrences of the +// opening bracket of a group and counted starting from 1 by step 1. If no +// substring fulfilling all conditions is found within the input string, +// an empty record of is returned. +// +/////////////////////////////////////////////////////////////////////////////// + type record of charstring_list t_list_of_charstring_list; + + external function f_pcre_regexp_list_all_matches(in charstring instr, + in charstring expression) return t_list_of_charstring_list; + } diff --git a/src/TCCSystem.cc b/src/TCCSystem.cc index 6e6b246..cd600c7 100644 --- a/src/TCCSystem.cc +++ b/src/TCCSystem.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2009 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCSystem.cc // Description: TCC Useful Functions: System Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2009-04-10 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// #include "TCCSystem_Functions.hh" diff --git a/src/TCCSystem_Functions.ttcn b/src/TCCSystem_Functions.ttcn index 82f925c..d7c3bfd 100644 --- a/src/TCCSystem_Functions.ttcn +++ b/src/TCCSystem_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2009 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCSystem_Functions.ttcn // Description: TCC Useful Functions: System Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2009-04-10 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCTemplate_Functions.ttcn b/src/TCCTemplate_Functions.ttcn index ed604a9..f1a77a9 100644 --- a/src/TCCTemplate_Functions.ttcn +++ b/src/TCCTemplate_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2007 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCTemplate_Functions.ttcn // Description: TCC Useful Functions: Template Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2007-12-20 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCTitanMetadata.cc b/src/TCCTitanMetadata.cc index cdec765..abb2007 100644 --- a/src/TCCTitanMetadata.cc +++ b/src/TCCTitanMetadata.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2007 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCTitanMetadata.cc // Description: TCC Useful Functions: TitanMetadata Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2007-10-26 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCTitanMetadata_Functions.ttcn b/src/TCCTitanMetadata_Functions.ttcn index 723c70a..decbb9f 100644 --- a/src/TCCTitanMetadata_Functions.ttcn +++ b/src/TCCTitanMetadata_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2007 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCTitanMetadata_Functions.ttcn // Description: TCC Useful Functions: TitanMetadata Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2007-10-26 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCUsefulFunctions_Library.grp b/src/TCCUsefulFunctions_Library.grp index a75bf7e..5fc46e2 100644 --- a/src/TCCUsefulFunctions_Library.grp +++ b/src/TCCUsefulFunctions_Library.grp @@ -1,21 +1,18 @@ <!-- /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2012 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) has been supplied. // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCUsefulFunctions_Library.grp // Description: FileGroup file for TCCUsefulFunctions ApplicationLibrary -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2012-03-26 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// --> @@ -38,6 +35,11 @@ <File path="TCCIPsec.cc" /> <File path="TCCIPsec_Definitions.ttcn" /> <File path="TCCIPsec_Functions.ttcn" /> + <File path="TCCIPsec_XFRM.cc" /> + <File path="TCCIPsec_XFRM.hh" /> + <File path="TCCIPsec_XFRM_Definitions.ttcn" /> + <File path="TCCIPsec_XFRM_SA.cc" /> + <File path="TCCIPsec_XFRM_SP.cc" /> <File path="TCCInterface.cc" /> <File path="TCCInterface_Functions.ttcn" /> <File path="TCCInterface_ip.h" /> diff --git a/src/TCCUsefulFunctions_PermutatedParameters.grp b/src/TCCUsefulFunctions_PermutatedParameters.grp index e8329ac..597c32d 100644 --- a/src/TCCUsefulFunctions_PermutatedParameters.grp +++ b/src/TCCUsefulFunctions_PermutatedParameters.grp @@ -1,21 +1,18 @@ <!-- /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2013 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) has been supplied. // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCUsefulFunctions_PermutatedParameters.grp // Description: FileGroup file for TCCUsefulFunctions Permutated Parameters -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2013-05-30 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// --> diff --git a/src/TCCXPathSupport.cc b/src/TCCXPathSupport.cc index 1df4da0..17058ff 100644 --- a/src/TCCXPathSupport.cc +++ b/src/TCCXPathSupport.cc @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2008 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCXPathSupport_Functions.ttcn // Description: TCC Useful Functions: XPath Support Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2008-08-26 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// diff --git a/src/TCCXPathSupport_Functions.ttcn b/src/TCCXPathSupport_Functions.ttcn index 895ad2d..1bc99e7 100644 --- a/src/TCCXPathSupport_Functions.ttcn +++ b/src/TCCXPathSupport_Functions.ttcn @@ -1,20 +1,17 @@ /////////////////////////////////////////////////////////////////////////////// -// // -// Copyright Test Competence Center (TCC) ETH 2008 // -// // -// The copyright to the computer program(s) herein is the property of TCC. // -// The program(s) may be used and/or copied only with the written permission // -// of TCC or in accordance with the terms and conditions stipulated in the // -// agreement/contract under which the program(s) have been supplied // -// // +// +// Copyright (c) 2000-2017 Ericsson Telecom AB +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://www.eclipse.org/legal/epl-v10.html /////////////////////////////////////////////////////////////////////////////// // // File: TCCXPathSupport_Functions.ttcn // Description: TCC Useful Functions: XPath Support Functions -// Rev: R25A +// Rev: R30A // Prodnr: CNL 113 472 -// Updated: 2008-08-26 -// Contact: http://ttcn.ericsson.se // /////////////////////////////////////////////////////////////////////////////// -- GitLab