Compare commits

...

33 Commits

Author SHA1 Message Date
5f4f71d43d
Possibly improved screenshots 2016-07-25 02:29:02 -04:00
rafalense
52a9c80de5 v3.8.1.2 added missing files 2016-05-26 11:52:53 +02:00
rafalense
852655432a v3.8.1.2
- New option to add chat shortcut to home screen
- Bug fixes and improvements
2016-05-26 07:18:06 +02:00
rafalense
7f03162332 - Added option to open user profile when channel message is signed
- If file name clicked in chat a toast will appear showing full file name
- If media message clicked 'Message' title will be replaced with file name in pop-up
- Bug fixes
2016-03-11 12:54:27 +01:00
rafalense
34bf879270 - Added option to open user profile when channel message is signed
- If file name clicked in chat a toast will appear showing full file name
- If media message clicked 'Message' title will be replaced with file name in pop-up
- Bug fixes
2016-03-11 12:50:47 +01:00
rafalense
a4e9947d42 - Added swipe left/right to change between tabs
- Added option to enable/disable infinite swipe between tabs
- Added new menu Plus and moved there all additional Plus features
- Added option to show/hide direct share button in any chat
- Added switch to use direct share without quoting sender
- Added date indicator toast in chat
- Added current download/upload size in chat screen
- Added sort options (default/unread) to all tabs
- Added different options in groups/supergroups for admins when user avatar is clicked in chat screen: ‘Show profile’, ‘Delete from group’ and ‘Set as admin’
- Added option to remove from admin list if user is already an admin
- Added ‘Mark as read’ for individual chats and ‘Mark all as read’ for every tab
- Added option in Plus settings to show username instead of mobile number in menu
- Bug fixes
2016-02-25 10:36:58 +01:00
rafalense
6c9a71f6d1 New in v3.3.1.1:
- Added user status indicator to main and chat screen
- Added option to hide status indicators
- Bug fixes
2015-12-02 14:33:29 +01:00
rafalense
c7be127b5c New in v3.3.1.0:
- Groups can now have multiple administrators with the ability to edit the name and logo, and add and remove members.
- Groups that have reached their capacity of 200 users can be upgraded to supergroups of up to 1,000 members.
- Channels got a new Quick Share button right next to messages.
2015-11-27 22:10:12 +01:00
rafalense
b0436c0971 - Bug fixes 2015-11-20 10:54:47 +01:00
rafalense
f1cce707bd - Now header gets color in android recent apps list (lollipop and up)
- Mention list size increased in chat screen
- Now also channels can be muted from main screen
- Added mod to set header avatar radius in chat screen
- Added mod to set 'typing' text color in chat header
- Bug fixes
2015-11-19 10:11:51 +01:00
rafalense
3f4ac76776 - Added mod for command color in chat screen
- Added mod for counter color background for muted chat/group/channel in main screen
- Added highlight search color mod in main screen
- Other improvements and bug fixes
2015-11-03 20:33:08 +01:00
rafalense
5f5081ce7c - New animations and many visual improvements
- Support for new emoji
- Android 6.0 support
- Now on Tap
- Direct Share
- Fingerprint support for Passcodes (Android 6.0 only)
- Other improvements and bug fixes
2015-10-31 12:17:13 +01:00
rafalense
6b94e8d180 - Added new option in settings to open profile or profile pics when clicking user or group pic in main screen
- Added gradient option to chat background color
- Added option to forward link without quoting
- Added link to official channel in menu
- Bug fixes
2015-10-21 18:27:19 +02:00
rafalense
8b5e9e2f0d - Now wallpaper can be changed directly from chat screen
- Improved way of applying themes' wallpapers
- Username copied to clipboard if clicked in profile screen
- Bug fixes
2015-09-30 15:47:40 +02:00
rafalense
30f85a08f3 - Added gradient option to header and list color in chats, chat, contacts, menu and profile
- Added gradient option to text entry box, emoji view and attach view
- MOD to change 'online' text color in profile and chat
- MOD to change avatars radius in profile
- Bug fixes
2015-09-09 18:36:48 +02:00
rafalense
2bed49fee0 * Base updated: v3.1.3
* New 'Shared Links' section in chat info
* In-app preview for links to photos
- v3.1.3.0
- New MOD to change default emoji tab icon color
- Bug fixes
2015-09-04 10:22:03 +02:00
rafalense
2b3d852636 - Base updated: v3.1.2
* Recent search results
* Tap and hold sticker to preview before sending
- Bug fixes
2015-08-27 18:32:51 +02:00
rafalense
3bc33bf670 - New bubble iOS added (thanks to Edwin Macalopu)
- New MOD to show username together with member name in groups
- Shows group admin in group profile. Admin user has its own icon
- New MOD to center avatar, name and phone in navigation menu
- New MOD to keep playing audio in chat disabling proximity sensor action
- New MOD to change icons color in profile screen
- Bug fixes
2015-08-14 15:45:42 +02:00
rafalense
b265320281 - New MOD to show contact avatar in chat screen
- New MOD to show own avatar in chat and group screen
- New MOD to align own avatar to top
- Added new bubbles Ed and Edge (thanks to Edwin Macalopu)
- New MOD to change background and text color in attach view in chat screen
- Added MOD to change color of dialog title and button
- Bug fixes
2015-08-04 09:17:15 +02:00
rafalense
75349fc1a8 Update to 3.1.1.3 (583):
- Base updated to 3.1.1:
* Search for messages inside a specific chat.
* Fully redesigned attachment menu. Send contacts and audio files straight from the attachment menu.
* Improved in-app media playback (YouTube, Vimeo, SoundСloud etc.), new player for large audio files.
More about this update: https://telegram.org/blog/search-and-media
- New MOD to change color of shared contact name
- New MODs to change avatar color, size and radius and status color in settings screen
- Bug fixes
2015-07-25 17:22:53 +02:00
rafalense
c32089f5eb Update to 3.0.1.6 (576):
- Fixed options to share music and stickers
- Added option to share contact number
- Added option to add member directly from group options
- Added option to mute or activate notifications from main screen
- Bug fixes
2015-07-08 20:40:14 +02:00
rafalense
4834528f60 Update to 2.9.1.4 (547):
- Option to change default emoji window size in chat screen (option in Settings/Messages)
- Option to change level of compression when sharing a video (android 4.3 and up)
- Added MODs to adjust Settings/Theming screen colors
- Added separated MODs for forward name color for right and left bubble in chat screen
- Added MOD to change icons colors in Contacts screen
- Added MOD to change color of 'Photo/Sticker' text in main screen
- Bug fixes
2015-06-05 09:53:03 +02:00
rafalense
788e3191ff Update to 2.9.1.1 (543):
-Install and share custom sticker sets like these ones:
https://telegram.me/addstickers/Animals
-If you're an artist, create custom sticker sets using our @stickers bot
-Use Plus Messenger with Android Auto
-Added MOD to set solid color for chat background
-Added MOD to hide background shadow of navigation menu
-Added MOD to set avatar radius in profile screen
-Bug fixes
2015-05-28 17:45:49 +02:00
rafalense
4dd544cf5e Update to 2.8.1.6 (526):
- Added option in navigation menu to open new Themes for Plus Messenger app (https://play.google.com/store/apps/details?id=es.rafalense.themes)
- "Delete chat" option inside chat is working again
- Now image and video caption gets color properly
- Bug showing replied/forwarded text when text input is transparent fixed
- Other minor bug fixes
2015-05-18 19:40:45 +02:00
rafalense
64970ee320 fixed untracked files 2015-05-06 16:32:28 +02:00
rafalense
8713d46f1b Update to 2.8.1.3 (523) 2015-05-06 16:17:21 +02:00
rafalense
d0d035cda2 Update to 2.7.0.1 (492) 2015-04-13 19:46:04 +02:00
rafalense
f07c7df1fa 2.6.1.1-475
*Add hashtags easily – recently used hashtags are instantly prompted after you input #
*Added sounds for outgoing and incoming messages in the currently opened conversation
*Long tap to clear search history for hashtags/gifs/images
*Custom backgrounds now shown in Menu drawer
+First emoticon will show all official Telegram stickers
+MOD to hide custom background in Menu drawer
+Option to set empty header title in main screen
+Passcode screen themed
+Bug fixes
2015-03-27 18:56:34 +01:00
rafalense
904dbb5665 Merge branch 'dev' of https://github.com/rafalense/Telegram into dev 2015-03-24 18:23:42 +01:00
rafalense
edd63aeac6 v2.6.0.2: New name, new base color, new app icon, replies, mentions and hashtags, added Polish, Croatian and Chinese (Taiwan) 2015-03-24 18:05:38 +01:00
rafalense
f7c5d9fb09 Reset BuildVars values 2015-03-11 17:03:31 +01:00
rafalense
e4c9e62f1b Update to 2.5.2.2 (Added Russian, Turkish, Catalan and Galician, navigation Drawer can be themed now, more theming options for Main and Chat screen) 2015-03-07 11:56:46 +01:00
rafalense
640d2bb9be Update to 2.5.2.1 2015-03-03 08:06:22 +01:00
3702 changed files with 494625 additions and 90287 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@ local.properties
gradle.properties
TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java
/TMessagesProj/google-services.json

View File

@ -1,24 +1,59 @@
### Telegram+ for Android
### Plus Messenger for Android (http://plusmessenger.org)
This is an UNOFFICIAL app that uses [Telegram's API](https://core.telegram.org/api)
It adds some extra features to the official Telegram app:
**THEMING:**
Plus Messenger is an UNOFFICIAL messaging app that uses Telegram's API
# One of the best rated messaging apps on Play Store #
Plus Messenger adds some extra features to official Telegram app:
# THEMING #
Change colors and sizes of many objects as texts, icons, headers... and create your own theme.
Save your theme and share it easily with your friends.
Apply themes shared by other users
Data base with more than 3000 different themes, updated every day, with all type of categories. New themes are published every day, notifying with every new publication
**MEDIA:** Audio files can be shared easily from Chat Screen
[Plus Themes](https://play.google.com/store/apps/details?id=es.rafalense.themes).
**PRIVACY:** Mobile number can be hidden from Menu Drawer and Settings menu
# EXTRA FEATURES #
+ Option to set own info (bio) in Settings
+ Option to leave a group without deleting it
+ Option to use direct share on any chat
+ Option to use direct share without quoting sender
+ Option to show phone emojis
+ Option to save files using original filename
+ Option to set custom compression when sharing videos
+ Option to use phone font
+ Option to show own photo or user photo in chat bubbles
+ Group admin is shown in groups profile
+ Option to discard proximity sensor changes when playing audio notes
+ Option to show profile pics when clicking photo in main screen
+ Option to show profile screen when clicking photo in main screen
+ Change wallpaper directly from chat screen
+ Option to change chat emoji view size
+ Option to mute users or groups directly from main screen
+ Option to add member directly from chat screen
**SOCIAL:** Get in touch with other Telegram+ users trough [our Google+ community](https://plus.google.com/communities/106927015963860485525)
In addition, it is translated to many other languages, updated by plus community continuously
This repo contains the source code for [Telegram+ App for Android](https://play.google.com/store/apps/details?id=org.telegram.plus).
Of course it has all Telegram benefits:
Free, fast and secure, private chats, files up to 15Gb, groups up to 200 members, channels, reply to concrete messages, no need to give your mobile number, just your username is enough to chat in a group or with any user, cloud based, etc
# SOCIAL #
Join our G+ community to report bugs, share ideas, get in touch with other Plus Messenger users through [our Google+ community](https://plus.google.com/communities/106927015963860485525)
Follow our [Official plus channel:] (https://telegram.me/plusmsgr)
This repo contains the source code for [Plus Messenger App for Android](https://play.google.com/store/apps/details?id=org.telegram.plus).
### USAGE
**Beware of using the dev branch and uploading it to any markets, in many cases it not will work as expected**.
First of all, take a look at **src/main/java/org/telegram/messenger/BuildVars.java** and fill it with correct values.
Import the root folder into your IDE (tested on Android Studio), then run project.
### LOCALIZATION
Join our translation project if you want to collaborate: [link](https://www.transifex.com/projects/p/plusmessenger/)

View File

@ -1,11 +1,3 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.1.0'
}
}
apply plugin: 'com.android.application'
repositories {
@ -13,16 +5,20 @@ repositories {
}
dependencies {
compile 'com.android.support:support-v4:21.0.+'
compile 'com.google.android.gms:play-services:3.2.+'
compile 'net.hockeyapp.android:HockeySDK:3.5.+'
compile 'com.android.support:support-v4:23.3.0'
compile "com.google.android.gms:play-services-gcm:8.4.0"
compile "com.google.android.gms:play-services-maps:8.4.0"
compile 'net.hockeyapp.android:HockeySDK:4.0.0-beta.1'
compile 'com.googlecode.mp4parser:isoparser:1.0.+'
compile 'com.android.support:recyclerview-v7:+'
}
android {
compileSdkVersion 21
buildToolsVersion '21.1.2'
compileSdkVersion 23
buildToolsVersion '23.0.3'
useLibrary 'org.apache.http.legacy'
//defaultConfig.applicationId = "org.telegram.messenger"
defaultConfig.applicationId = "org.telegram.plus"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
@ -32,6 +28,10 @@ android {
signingConfigs {
debug {
storeFile file("config/debug.keystore")
//storeFile file("config/release.keystore")
//storePassword RELEASE_STORE_PASSWORD
//keyAlias RELEASE_KEY_ALIAS
//keyPassword RELEASE_KEY_PASSWORD
}
release {
@ -47,12 +47,15 @@ android {
debuggable true
jniDebuggable true
signingConfig signingConfigs.debug
applicationIdSuffix ".beta"
}
release {
debuggable false
jniDebuggable false
//signingConfig signingConfigs.release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
foss {
@ -62,6 +65,10 @@ android {
}
}
defaultConfig.versionCode = 798
defaultConfig.manifestPlaceholders = [HOCKEYAPP_APP_ID: ""]
sourceSets.main {
jniLibs.srcDir 'libs'
jni.srcDirs = [] //disable automatic ndk-build call
@ -84,11 +91,40 @@ android {
abortOnError false
}
defaultConfig {
applicationId "org.telegram.plus"
minSdkVersion 8
targetSdkVersion 21
versionCode 458
versionName "2.5.2.1"
productFlavors {
arm {
ndk {
abiFilter "armeabi"
}
versionCode = 0
}
armv7 {
ndk {
abiFilter "armeabi-v7a"
}
versionCode = 1
}
x86 {
ndk {
abiFilter "x86"
}
versionCode = 2
}
fat {
versionCode = 3
}
}
}
applicationVariants.all { variant ->
def abiVersion = variant.productFlavors.get(0).versionCode
variant.mergedFlavor.versionCode = defaultConfig.versionCode * 10 + abiVersion;
}
defaultConfig {
minSdkVersion 9
targetSdkVersion 23
versionName "3.8.1.2"
}
}
apply plugin: 'com.google.gms.google-services'

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.telegram.messenger"
android:installLocation="auto">
@ -9,40 +10,71 @@
<uses-feature android:name="android.hardware.LOCATION" android:required="false" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="org.telegram.plus.permission.MAPS_RECEIVE"/>
<uses-permission android:name="org.telegram.plus.permission.C2D_MESSAGE" />
<uses-permission android:name="org.telegram.plus.beta.permission.MAPS_RECEIVE"/>
<uses-permission android:name="org.telegram.plus.beta.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<permission android:name="org.telegram.plus.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
<permission android:name="org.telegram.plus.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<permission android:name="org.telegram.plus.beta.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
<permission android:name="org.telegram.plus.beta.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<permission android:name="org.telegram.plus.beta.android.provider.ACCESS" android:protectionLevel="signature"/>
<application
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/AppName"
tools:replace="android:icon"
android:icon="@drawable/ic_launcher_beta"
android:label="Plus beta"
android:theme="@style/Theme.TMessages.Start"
android:name=".ApplicationLoader"
android:name="org.telegram.messenger.ApplicationLoader"
android:hardwareAccelerated="@bool/useHardwareAcceleration"
android:largeHeap="true">
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AIzaSyCZi83oDrfsCQ3_Aokfmlv53gTBYPIGJ2Q" /><!--AIzaSyCq2oezhsHUM0e_FPU-DpP93c0WxpEK4Fc-->
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AIzaSyDFiyV4uu3lh66i_Jyn0mmhrJMNLyo2-0s" /><!--org.telegram.plus/AIzaSyCZi83oDrfsCQ3_Aokfmlv53gTBYPIGJ2Q-->
<activity android:name="net.hockeyapp.android.UpdateActivity" />
<activity android:name="net.hockeyapp.android.LoginActivity" />
<meta-data android:name="net.hockeyapp.android.appIdentifier" android:value="${HOCKEYAPP_APP_ID}" />
<receiver
android:name="org.telegram.android.GcmBroadcastReceiver"
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="org.telegram.plus" />
<category android:name="org.telegram.plus.beta" />
</intent-filter>
</receiver>
<service
android:name="org.telegram.messenger.GcmPushListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name="org.telegram.messenger.GcmInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<service
android:name="org.telegram.messenger.GcmRegistrationIntentService"
android:exported="false">
</service>
<uses-library android:name="com.google.android.maps" android:required="false"/>
<provider
android:authorities="org.telegram.plus.beta.android.provider.content"
android:name="org.telegram.messenger.ModuleContentProvider"
android:label="Plus beta"
android:exported="true"
android:permission="org.telegram.plus.beta.android.provider.ACCESS" />
</application>
</manifest>

View File

@ -17,13 +17,15 @@
<permission android:name="org.telegram.plus.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
<permission android:name="org.telegram.plus.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<permission android:name="org.telegram.plus.android.provider.ACCESS" android:protectionLevel="signature"/>
<application
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="@string/AppName"
android:label="@string/ShortAppName"
android:theme="@style/Theme.TMessages.Start"
android:name=".ApplicationLoader"
android:name="org.telegram.messenger.ApplicationLoader"
android:hardwareAccelerated="@bool/useHardwareAcceleration"
android:largeHeap="true">
@ -32,7 +34,8 @@
<activity android:name="net.hockeyapp.android.UpdateActivity" />
<receiver
android:name="org.telegram.android.GcmBroadcastReceiver"
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
@ -40,8 +43,33 @@
<category android:name="org.telegram.plus" />
</intent-filter>
</receiver>
<service
android:name="org.telegram.messenger.GcmPushListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name="org.telegram.messenger.GcmInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<service
android:name="org.telegram.messenger.GcmRegistrationIntentService"
android:exported="false">
</service>
<uses-library android:name="com.google.android.maps" android:required="false"/>
<provider
android:authorities="org.telegram.plus.android.provider.content"
android:name="org.telegram.messenger.ModuleContentProvider"
android:label="@string/AppName"
android:exported="true"
android:permission="org.telegram.plus.android.provider.ACCESS" />
</application>

250
TMessagesProj/jni/Android.mk Executable file → Normal file
View File

@ -1,17 +1,148 @@
LOCAL_PATH := $(call my-dir)
LOCAL_MODULE := avutil
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_SRC_FILES := ./ffmpeg/armv7-a/libavutil.a
else
ifeq ($(TARGET_ARCH_ABI),armeabi)
LOCAL_SRC_FILES := ./ffmpeg/armv5te/libavutil.a
else
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_SRC_FILES := ./ffmpeg/i686/libavutil.a
endif
endif
endif
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD -DWEBP_USE_THREAD -finline-functions -ffast-math -ffunction-sections -fdata-sections -O2
LOCAL_C_INCLUDES += ./libwebp/src
LOCAL_MODULE := avformat
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_SRC_FILES := ./ffmpeg/armv7-a/libavformat.a
else
ifeq ($(TARGET_ARCH_ABI),armeabi)
LOCAL_SRC_FILES := ./ffmpeg/armv5te/libavformat.a
else
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_SRC_FILES := ./ffmpeg/i686/libavformat.a
endif
endif
endif
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avcodec
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_SRC_FILES := ./ffmpeg/armv7-a/libavcodec.a
else
ifeq ($(TARGET_ARCH_ABI),armeabi)
LOCAL_SRC_FILES := ./ffmpeg/armv5te/libavcodec.a
else
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_SRC_FILES := ./ffmpeg/i686/libavcodec.a
endif
endif
endif
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := crypto
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_SRC_FILES := ./boringssl/lib/libcrypto_armeabi-v7a.a
else
ifeq ($(TARGET_ARCH_ABI),armeabi)
LOCAL_SRC_FILES := ./boringssl/lib/libcrypto_armeabi.a
else
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_SRC_FILES := ./boringssl/lib/libcrypto_x86.a
endif
endif
endif
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cc
LOCAL_ARM_MODE := arm
LOCAL_MODULE := breakpad
LOCAL_CPPFLAGS := -Wall -std=c++11 -DANDROID -finline-functions -ffast-math -Os -fno-strict-aliasing
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/breakpad/common/android/include \
$(LOCAL_PATH)/breakpad
LOCAL_SRC_FILES := \
./breakpad/client/linux/crash_generation/crash_generation_client.cc \
./breakpad/client/linux/dump_writer_common/ucontext_reader.cc \
./breakpad/client/linux/dump_writer_common/thread_info.cc \
./breakpad/client/linux/handler/exception_handler.cc \
./breakpad/client/linux/handler/minidump_descriptor.cc \
./breakpad/client/linux/log/log.cc \
./breakpad/client/linux/microdump_writer/microdump_writer.cc \
./breakpad/client/linux/minidump_writer/linux_dumper.cc \
./breakpad/client/linux/minidump_writer/linux_ptrace_dumper.cc \
./breakpad/client/linux/minidump_writer/minidump_writer.cc \
./breakpad/client/minidump_file_writer.cc \
./breakpad/common/android/breakpad_getcontext.S \
./breakpad/common/convert_UTF.c \
./breakpad/common/md5.cc \
./breakpad/common/string_conversion.cc \
./breakpad/common/linux/elfutils.cc \
./breakpad/common/linux/file_id.cc \
./breakpad/common/linux/guid_creator.cc \
./breakpad/common/linux/linux_libc_support.cc \
./breakpad/common/linux/memory_mapped_file.cc \
./breakpad/common/linux/safe_readlink.cc
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_CPPFLAGS := -Wall -std=c++11 -DANDROID -frtti -DHAVE_PTHREAD -finline-functions -ffast-math -Os
LOCAL_C_INCLUDES += $(LOCAL_PATH)/boringssl/include/
LOCAL_ARM_MODE := arm
LOCAL_MODULE := tgnet
LOCAL_STATIC_LIBRARIES := crypto
LOCAL_SRC_FILES := \
./tgnet/BuffersStorage.cpp \
./tgnet/ByteArray.cpp \
./tgnet/ByteStream.cpp \
./tgnet/Connection.cpp \
./tgnet/ConnectionSession.cpp \
./tgnet/ConnectionsManager.cpp \
./tgnet/ConnectionSocket.cpp \
./tgnet/Datacenter.cpp \
./tgnet/EventObject.cpp \
./tgnet/FileLog.cpp \
./tgnet/MTProtoScheme.cpp \
./tgnet/NativeByteBuffer.cpp \
./tgnet/Request.cpp \
./tgnet/Timer.cpp \
./tgnet/TLObject.cpp \
./tgnet/Config.cpp
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_CFLAGS := -Wall -DANDROID -DHAVE_MALLOC_H -DHAVE_PTHREAD -DWEBP_USE_THREAD -finline-functions -ffast-math -ffunction-sections -fdata-sections -Os
LOCAL_C_INCLUDES += $(LOCAL_PATH)/libwebp/src
LOCAL_ARM_MODE := arm
LOCAL_STATIC_LIBRARIES := cpufeatures
LOCAL_MODULE := webp
ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),)
# Setting LOCAL_ARM_NEON will enable -mfpu=neon which may cause illegal
# instructions to be generated for armv7a code. Instead target the neon code
# specifically.
NEON := c.neon
else
NEON := c
@ -93,7 +224,7 @@ else
LOCAL_ARM_MODE := arm
endif
LOCAL_MODULE := sqlite
LOCAL_CFLAGS := -w -std=gnu99 -O2 -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
LOCAL_CFLAGS := -w -std=c11 -Os -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -DHAVE_STRCHRNUL=0
LOCAL_SRC_FILES := \
@ -103,18 +234,14 @@ include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_STATIC_LIBRARIES := webp sqlite
LOCAL_MODULE := tmessages.6
LOCAL_CFLAGS := -w -std=gnu99 -O2 -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
LOCAL_MODULE := tmessages.21
LOCAL_CFLAGS := -w -std=c11 -Os -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-math-errno
LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math
LOCAL_CPPFLAGS := -DBSD=1 -ffast-math -O2 -funroll-loops
LOCAL_LDLIBS := -ljnigraphics -llog
ifeq ($(TARGET_ARCH_ABI),armeabi)
LOCAL_ARM_MODE := thumb
else
LOCAL_ARM_MODE := arm
endif
LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math -D__STDC_CONSTANT_MACROS
LOCAL_CPPFLAGS := -DBSD=1 -ffast-math -Os -funroll-loops -std=c++11
LOCAL_LDLIBS := -ljnigraphics -llog -lz -latomic
LOCAL_STATIC_LIBRARIES := webp sqlite tgnet breakpad avformat avcodec avutil
LOCAL_SRC_FILES := \
./opus/src/opus.c \
@ -128,6 +255,23 @@ LOCAL_SRC_FILES := \
./opus/src/mlp.c \
./opus/src/mlp_data.c
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_ARM_MODE := arm
LOCAL_CPPFLAGS += -DLIBYUV_NEON
LOCAL_CFLAGS += -DLIBYUV_NEON
else
ifeq ($(TARGET_ARCH_ABI),armeabi)
LOCAL_ARM_MODE := arm
else
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_ARM_MODE := arm
LOCAL_SRC_FILE += \
./libyuv/source/row_x86.asm
endif
endif
endif
LOCAL_SRC_FILES += \
./opus/silk/CNG.c \
./opus/silk/code_signs.c \
@ -263,36 +407,18 @@ LOCAL_SRC_FILES += \
./opus/opusfile/opusfile.c \
./opus/opusfile/stream.c
LOCAL_SRC_FILES += \
./giflib/dgif_lib.c \
./giflib/gifalloc.c
LOCAL_SRC_FILES += \
./aes/aes_ige.c \
./aes/aes_misc.c
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_SRC_FILES += ./aes/aes_arm.S
else
ifeq ($(TARGET_ARCH_ABI),armeabi)
LOCAL_SRC_FILES += ./aes/aes_arm.S
else
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_SRC_FILES += ./aes/aes_core.c
else
LOCAL_SRC_FILES += ./aes/aes_core.c
endif
endif
endif
LOCAL_C_INCLUDES := \
./opus/include \
./opus/silk \
./opus/silk/fixed \
./opus/celt \
./opus/ \
./opus/opusfile \
./libyuv/include
$(LOCAL_PATH)/opus/include \
$(LOCAL_PATH)/opus/silk \
$(LOCAL_PATH)/opus/silk/fixed \
$(LOCAL_PATH)/opus/celt \
$(LOCAL_PATH)/opus/ \
$(LOCAL_PATH)/opus/opusfile \
$(LOCAL_PATH)/libyuv/include \
$(LOCAL_PATH)/boringssl/include \
$(LOCAL_PATH)/breakpad/common/android/include \
$(LOCAL_PATH)/breakpad \
$(LOCAL_PATH)/ffmpeg/include
LOCAL_SRC_FILES += \
./libjpeg/jcapimin.c \
@ -345,8 +471,8 @@ LOCAL_SRC_FILES += \
LOCAL_SRC_FILES += \
./libyuv/source/compare_common.cc \
./libyuv/source/compare_neon.cc \
./libyuv/source/compare_posix.cc \
./libyuv/source/compare_gcc.cc \
./libyuv/source/compare_neon64.cc \
./libyuv/source/compare_win.cc \
./libyuv/source/compare.cc \
./libyuv/source/convert_argb.cc \
@ -357,32 +483,42 @@ LOCAL_SRC_FILES += \
./libyuv/source/convert_to_i420.cc \
./libyuv/source/convert.cc \
./libyuv/source/cpu_id.cc \
./libyuv/source/format_conversion.cc \
./libyuv/source/mjpeg_decoder.cc \
./libyuv/source/mjpeg_validate.cc \
./libyuv/source/planar_functions.cc \
./libyuv/source/rotate_any.cc \
./libyuv/source/rotate_argb.cc \
./libyuv/source/rotate_common.cc \
./libyuv/source/rotate_gcc.cc \
./libyuv/source/rotate_mips.cc \
./libyuv/source/rotate_neon.cc \
./libyuv/source/rotate_neon64.cc \
./libyuv/source/rotate_win.cc \
./libyuv/source/rotate.cc \
./libyuv/source/row_any.cc \
./libyuv/source/row_common.cc \
./libyuv/source/row_gcc.cc \
./libyuv/source/row_mips.cc \
./libyuv/source/row_neon.cc \
./libyuv/source/row_neon64.cc \
./libyuv/source/row_posix.cc \
./libyuv/source/row_win.cc \
./libyuv/source/scale_any.cc \
./libyuv/source/scale_argb.cc \
./libyuv/source/scale_common.cc \
./libyuv/source/scale_gcc.cc \
./libyuv/source/scale_mips.cc \
./libyuv/source/scale_neon.cc \
./libyuv/source/scale_neon64.cc \
./libyuv/source/scale_posix.cc \
./libyuv/source/scale_win.cc \
./libyuv/source/scale.cc \
./libyuv/source/video_common.cc
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_CFLAGS += -DLIBYUV_NEON
LOCAL_SRC_FILES += \
./libyuv/source/compare_neon.cc.neon \
./libyuv/source/rotate_neon.cc.neon \
./libyuv/source/row_neon.cc.neon \
./libyuv/source/scale_neon.cc.neon
endif
LOCAL_SRC_FILES += \
./jni.c \
./sqlite_cursor.c \
@ -390,10 +526,12 @@ LOCAL_SRC_FILES += \
./sqlite_statement.c \
./sqlite.c \
./audio.c \
./gif.c \
./utils.c \
./image.c \
./video.c
./video.c \
./gifvideo.cpp \
./TgNetWrapper.cpp \
./NativeLoader.cpp
include $(BUILD_SHARED_LIBRARY)

View File

@ -1,2 +1,4 @@
APP_PLATFORM := android-9
APP_ABI := armeabi armeabi-v7a x86
APP_ABI := armeabi armeabi-v7a x86
NDK_TOOLCHAIN_VERSION := 4.9
APP_STL := gnustl_static

View File

@ -0,0 +1,22 @@
#include <jni.h>
#include <stdio.h>
#include "breakpad/client/linux/handler/exception_handler.h"
#include "breakpad/client/linux/handler/minidump_descriptor.h"
/*static google_breakpad::ExceptionHandler *exceptionHandler;
bool callback(const google_breakpad::MinidumpDescriptor &descriptor, void *context, bool succeeded) {
printf("dump path: %s\n", descriptor.path());
return succeeded;
}*/
extern "C" {
void Java_org_telegram_messenger_NativeLoader_init(JNIEnv* env, jobject obj, jstring filepath, bool enable) {
return;
/*if (enable) {
const char *path = env->GetStringUTFChars(filepath, 0);
google_breakpad::MinidumpDescriptor descriptor(path);
exceptionHandler = new google_breakpad::ExceptionHandler(descriptor, NULL, callback, NULL, true, -1);
}*/
}
}

View File

@ -0,0 +1,336 @@
#include <jni.h>
#include "tgnet/BuffersStorage.h"
#include "tgnet/NativeByteBuffer.h"
#include "tgnet/ConnectionsManager.h"
#include "tgnet/MTProtoScheme.h"
#include "tgnet/FileLog.h"
JavaVM *java;
jclass jclass_RequestDelegateInternal;
jmethodID jclass_RequestDelegateInternal_run;
jclass jclass_QuickAckDelegate;
jmethodID jclass_QuickAckDelegate_run;
jclass jclass_ConnectionsManager;
jmethodID jclass_ConnectionsManager_onUnparsedMessageReceived;
jmethodID jclass_ConnectionsManager_onUpdate;
jmethodID jclass_ConnectionsManager_onSessionCreated;
jmethodID jclass_ConnectionsManager_onLogout;
jmethodID jclass_ConnectionsManager_onConnectionStateChanged;
jmethodID jclass_ConnectionsManager_onInternalPushReceived;
jmethodID jclass_ConnectionsManager_onUpdateConfig;
jint getFreeBuffer(JNIEnv *env, jclass c, jint length) {
return (jint) BuffersStorage::getInstance().getFreeBuffer(length);
}
jint limit(JNIEnv *env, jclass c, jint address) {
NativeByteBuffer *buffer = (NativeByteBuffer *) address;
return buffer->limit();
}
jint position(JNIEnv *env, jclass c, jint address) {
NativeByteBuffer *buffer = (NativeByteBuffer *) address;
return buffer->position();
}
void reuse(JNIEnv *env, jclass c, jint address) {
NativeByteBuffer *buffer = (NativeByteBuffer *) address;
buffer->reuse();
}
jobject getJavaByteBuffer(JNIEnv *env, jclass c, jint address) {
NativeByteBuffer *buffer = (NativeByteBuffer *) address;
return buffer->getJavaByteBuffer();
}
static const char *NativeByteBufferClassPathName = "org/telegram/tgnet/NativeByteBuffer";
static JNINativeMethod NativeByteBufferMethods[] = {
{"native_getFreeBuffer", "(I)I", (void *) getFreeBuffer},
{"native_limit", "(I)I", (void *) limit},
{"native_position", "(I)I", (void *) position},
{"native_reuse", "(I)V", (void *) reuse},
{"native_getJavaByteBuffer", "(I)Ljava/nio/ByteBuffer;", (void *) getJavaByteBuffer}
};
jlong getCurrentTimeMillis(JNIEnv *env, jclass c) {
return ConnectionsManager::getInstance().getCurrentTimeMillis();
}
jint getCurrentTime(JNIEnv *env, jclass c) {
return ConnectionsManager::getInstance().getCurrentTime();
}
jint getTimeDifference(JNIEnv *env, jclass c) {
return ConnectionsManager::getInstance().getTimeDifference();
}
void sendRequest(JNIEnv *env, jclass c, jint object, jobject onComplete, jobject onQuickAck, jint flags, jint datacenterId, jint connetionType, jboolean immediate, jint token) {
TL_api_request *request = new TL_api_request();
request->request = (NativeByteBuffer *) object;
if (onComplete != nullptr) {
onComplete = env->NewGlobalRef(onComplete);
}
if (onQuickAck != nullptr) {
onQuickAck = env->NewGlobalRef(onQuickAck);
}
ConnectionsManager::getInstance().sendRequest(request, ([onComplete](TLObject *response, TL_error *error) {
TL_api_response *resp = (TL_api_response *) response;
jint ptr = 0;
jint errorCode = 0;
jstring errorText = nullptr;
if (resp != nullptr) {
ptr = (jint) resp->response.get();
} else if (error != nullptr) {
errorCode = error->code;
errorText = jniEnv->NewStringUTF(error->text.c_str());
}
if (onComplete != nullptr) {
jniEnv->CallVoidMethod(onComplete, jclass_RequestDelegateInternal_run, ptr, errorCode, errorText);
}
if (errorText != nullptr) {
jniEnv->DeleteLocalRef(errorText);
}
}), ([onQuickAck] {
if (onQuickAck != nullptr) {
jniEnv->CallVoidMethod(onQuickAck, jclass_QuickAckDelegate_run);
}
}), flags, datacenterId, (ConnectionType) connetionType, immediate, token, onComplete, onQuickAck);
}
void cancelRequest(JNIEnv *env, jclass c, jint token, jboolean notifyServer) {
return ConnectionsManager::getInstance().cancelRequest(token, notifyServer);
}
void cleanUp(JNIEnv *env, jclass c) {
return ConnectionsManager::getInstance().cleanUp();
}
void cancelRequestsForGuid(JNIEnv *env, jclass c, jint guid) {
return ConnectionsManager::getInstance().cancelRequestsForGuid(guid);
}
void bindRequestToGuid(JNIEnv *env, jclass c, jint requestToken, jint guid) {
return ConnectionsManager::getInstance().bindRequestToGuid(requestToken, guid);
}
void applyDatacenterAddress(JNIEnv *env, jclass c, jint datacenterId, jstring ipAddress, jint port) {
const char *valueStr = env->GetStringUTFChars(ipAddress, 0);
ConnectionsManager::getInstance().applyDatacenterAddress(datacenterId, std::string(valueStr), port);
if (valueStr != 0) {
env->ReleaseStringUTFChars(ipAddress, valueStr);
}
}
jint getConnectionState(JNIEnv *env, jclass c) {
return ConnectionsManager::getInstance().getConnectionState();
}
void setUserId(JNIEnv *env, jclass c, int32_t id) {
ConnectionsManager::getInstance().setUserId(id);
}
void switchBackend(JNIEnv *env, jclass c) {
ConnectionsManager::getInstance().switchBackend();
}
void pauseNetwork(JNIEnv *env, jclass c) {
ConnectionsManager::getInstance().pauseNetwork();
}
void resumeNetwork(JNIEnv *env, jclass c, jboolean partial) {
ConnectionsManager::getInstance().resumeNetwork(partial);
}
void updateDcSettings(JNIEnv *env, jclass c) {
ConnectionsManager::getInstance().updateDcSettings(0);
}
void setUseIpv6(JNIEnv *env, jclass c, bool value) {
ConnectionsManager::getInstance().setUseIpv6(value);
}
void setNetworkAvailable(JNIEnv *env, jclass c, jboolean value) {
ConnectionsManager::getInstance().setNetworkAvailable(value);
}
void setPushConnectionEnabled(JNIEnv *env, jclass c, jboolean value) {
ConnectionsManager::getInstance().setPushConnectionEnabled(value);
}
class Delegate : public ConnectiosManagerDelegate {
void onUpdate() {
jniEnv->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onUpdate);
}
void onSessionCreated() {
jniEnv->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onSessionCreated);
}
void onConnectionStateChanged(ConnectionState state) {
jniEnv->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onConnectionStateChanged, state);
}
void onUnparsedMessageReceived(int64_t reqMessageId, NativeByteBuffer *buffer, ConnectionType connectionType) {
if (connectionType == ConnectionTypeGeneric) {
jniEnv->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onUnparsedMessageReceived, buffer);
}
}
void onLogout() {
jniEnv->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onLogout);
}
void onUpdateConfig(TL_config *config) {
NativeByteBuffer *buffer = BuffersStorage::getInstance().getFreeBuffer(config->getObjectSize());
config->serializeToStream(buffer);
buffer->position(0);
jniEnv->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onUpdateConfig, buffer);
buffer->reuse();
}
void onInternalPushReceived() {
jniEnv->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onInternalPushReceived);
}
};
void init(JNIEnv *env, jclass c, jint version, jint layer, jint apiId, jstring deviceModel, jstring systemVersion, jstring appVersion, jstring langCode, jstring configPath, jstring logPath, jint userId, jboolean enablePushConnection) {
const char *deviceModelStr = env->GetStringUTFChars(deviceModel, 0);
const char *systemVersionStr = env->GetStringUTFChars(systemVersion, 0);
const char *appVersionStr = env->GetStringUTFChars(appVersion, 0);
const char *langCodeStr = env->GetStringUTFChars(langCode, 0);
const char *configPathStr = env->GetStringUTFChars(configPath, 0);
const char *logPathStr = env->GetStringUTFChars(logPath, 0);
ConnectionsManager::getInstance().init(version, layer, apiId, std::string(deviceModelStr), std::string(systemVersionStr), std::string(appVersionStr), std::string(langCodeStr), std::string(configPathStr), std::string(logPathStr), userId, true, enablePushConnection);
if (deviceModelStr != 0) {
env->ReleaseStringUTFChars(deviceModel, deviceModelStr);
}
if (systemVersionStr != 0) {
env->ReleaseStringUTFChars(systemVersion, systemVersionStr);
}
if (appVersionStr != 0) {
env->ReleaseStringUTFChars(appVersion, appVersionStr);
}
if (langCodeStr != 0) {
env->ReleaseStringUTFChars(langCode, langCodeStr);
}
if (configPathStr != 0) {
env->ReleaseStringUTFChars(configPath, configPathStr);
}
if (logPathStr != 0) {
env->ReleaseStringUTFChars(logPath, logPathStr);
}
}
void setJava(JNIEnv *env, jclass c, jboolean useJavaByteBuffers) {
ConnectionsManager::useJavaVM(java, useJavaByteBuffers);
ConnectionsManager::getInstance().setDelegate(new Delegate());
}
static const char *ConnectionsManagerClassPathName = "org/telegram/tgnet/ConnectionsManager";
static JNINativeMethod ConnectionsManagerMethods[] = {
{"native_getCurrentTimeMillis", "()J", (void *) getCurrentTimeMillis},
{"native_getCurrentTime", "()I", (void *) getCurrentTime},
{"native_getTimeDifference", "()I", (void *) getTimeDifference},
{"native_sendRequest", "(ILorg/telegram/tgnet/RequestDelegateInternal;Lorg/telegram/tgnet/QuickAckDelegate;IIIZI)V", (void *) sendRequest},
{"native_cancelRequest", "(IZ)V", (void *) cancelRequest},
{"native_cleanUp", "()V", (void *) cleanUp},
{"native_cancelRequestsForGuid", "(I)V", (void *) cancelRequestsForGuid},
{"native_bindRequestToGuid", "(II)V", (void *) bindRequestToGuid},
{"native_applyDatacenterAddress", "(ILjava/lang/String;I)V", (void *) applyDatacenterAddress},
{"native_getConnectionState", "()I", (void *) getConnectionState},
{"native_setUserId", "(I)V", (void *) setUserId},
{"native_init", "(IIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZ)V", (void *) init},
{"native_switchBackend", "()V", (void *) switchBackend},
{"native_pauseNetwork", "()V", (void *) pauseNetwork},
{"native_resumeNetwork", "(Z)V", (void *) resumeNetwork},
{"native_updateDcSettings", "()V", (void *) updateDcSettings},
{"native_setUseIpv6", "(Z)V", (void *) setUseIpv6},
{"native_setNetworkAvailable", "(Z)V", (void *) setNetworkAvailable},
{"native_setPushConnectionEnabled", "(Z)V", (void *) setPushConnectionEnabled},
{"native_setJava", "(Z)V", (void *) setJava}
};
inline int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int methodsCount) {
jclass clazz;
clazz = env->FindClass(className);
if (clazz == NULL) {
return JNI_FALSE;
}
if (env->RegisterNatives(clazz, methods, methodsCount) < 0) {
return JNI_FALSE;
}
return JNI_TRUE;
}
extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
java = vm;
if (!registerNativeMethods(env, NativeByteBufferClassPathName, NativeByteBufferMethods, sizeof(NativeByteBufferMethods) / sizeof(NativeByteBufferMethods[0]))) {
return JNI_FALSE;
}
if (!registerNativeMethods(env, ConnectionsManagerClassPathName, ConnectionsManagerMethods, sizeof(ConnectionsManagerMethods) / sizeof(ConnectionsManagerMethods[0]))) {
return JNI_FALSE;
}
jclass_RequestDelegateInternal = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/RequestDelegateInternal"));
if (jclass_RequestDelegateInternal == 0) {
return JNI_FALSE;
}
jclass_RequestDelegateInternal_run = env->GetMethodID(jclass_RequestDelegateInternal, "run", "(IILjava/lang/String;)V");
if (jclass_RequestDelegateInternal_run == 0) {
return JNI_FALSE;
}
jclass_QuickAckDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/QuickAckDelegate"));
if (jclass_RequestDelegateInternal == 0) {
return JNI_FALSE;
}
jclass_QuickAckDelegate_run = env->GetMethodID(jclass_QuickAckDelegate, "run", "()V");
if (jclass_QuickAckDelegate_run == 0) {
return JNI_FALSE;
}
jclass_ConnectionsManager = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/ConnectionsManager"));
if (jclass_ConnectionsManager == 0) {
return JNI_FALSE;
}
jclass_ConnectionsManager_onUnparsedMessageReceived = env->GetStaticMethodID(jclass_ConnectionsManager, "onUnparsedMessageReceived", "(I)V");
if (jclass_ConnectionsManager_onUnparsedMessageReceived == 0) {
return JNI_FALSE;
}
jclass_ConnectionsManager_onUpdate = env->GetStaticMethodID(jclass_ConnectionsManager, "onUpdate", "()V");
if (jclass_ConnectionsManager_onUpdate == 0) {
return JNI_FALSE;
}
jclass_ConnectionsManager_onSessionCreated = env->GetStaticMethodID(jclass_ConnectionsManager, "onSessionCreated", "()V");
if (jclass_ConnectionsManager_onSessionCreated == 0) {
return JNI_FALSE;
}
jclass_ConnectionsManager_onLogout = env->GetStaticMethodID(jclass_ConnectionsManager, "onLogout", "()V");
if (jclass_ConnectionsManager_onLogout == 0) {
return JNI_FALSE;
}
jclass_ConnectionsManager_onConnectionStateChanged = env->GetStaticMethodID(jclass_ConnectionsManager, "onConnectionStateChanged", "(I)V");
if (jclass_ConnectionsManager_onConnectionStateChanged == 0) {
return JNI_FALSE;
}
jclass_ConnectionsManager_onInternalPushReceived = env->GetStaticMethodID(jclass_ConnectionsManager, "onInternalPushReceived", "()V");
if (jclass_ConnectionsManager_onInternalPushReceived == 0) {
return JNI_FALSE;
}
jclass_ConnectionsManager_onUpdateConfig = env->GetStaticMethodID(jclass_ConnectionsManager, "onUpdateConfig", "(I)V");
if (jclass_ConnectionsManager_onUpdateConfig == 0) {
return JNI_FALSE;
}
ConnectionsManager::getInstance().setDelegate(new Delegate());
return JNI_TRUE;
}

View File

@ -1,147 +0,0 @@
/* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
*/
#ifndef HEADER_AES_H
#define HEADER_AES_H
//#include <openssl/opensslconf.h>
#ifdef OPENSSL_NO_AES
#error AES is disabled.
#endif
#include <stddef.h>
#define AES_ENCRYPT 1
#define AES_DECRYPT 0
/* Because array size can't be a const in C, the following two are macros.
Both sizes are in bytes. */
#define AES_MAXNR 14
#define AES_BLOCK_SIZE 16
#ifdef __cplusplus
extern "C" {
#endif
/* This should be a hidden type, but EVP requires that the size be known */
struct aes_key_st {
#ifdef AES_LONG
unsigned long rd_key[4 *(AES_MAXNR + 1)];
#else
unsigned int rd_key[4 *(AES_MAXNR + 1)];
#endif
int rounds;
};
typedef struct aes_key_st AES_KEY;
const char *AES_options(void);
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
void AES_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void AES_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key, const int enc);
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num, const int enc);
void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, int *num);
void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char ivec[AES_BLOCK_SIZE],
unsigned char ecount_buf[AES_BLOCK_SIZE],
unsigned int *num);
/* NB: the IV is _two_ blocks long */
void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
/* NB: the IV is _four_ blocks long */
void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
const AES_KEY *key2, const unsigned char *ivec,
const int enc);
int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen);
int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, unsigned int inlen);
#ifdef __cplusplus
}
#endif
#endif /* !HEADER_AES_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,51 +0,0 @@
#ifndef __ARM_ARCH_H__
#define __ARM_ARCH_H__
#if !defined(__ARM_ARCH__)
# if defined(__CC_ARM)
# define __ARM_ARCH__ __TARGET_ARCH_ARM
# if defined(__BIG_ENDIAN)
# define __ARMEB__
# else
# define __ARMEL__
# endif
# elif defined(__GNUC__)
/*
* Why doesn't gcc define __ARM_ARCH__? Instead it defines
* bunch of below macros. See all_architectires[] table in
* gcc/config/arm/arm.c. On a side note it defines
* __ARMEL__/__ARMEB__ for little-/big-endian.
*/
# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__) || \
defined(__ARM_ARCH_7EM__)
# define __ARM_ARCH__ 7
# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
defined(__ARM_ARCH_6K__)|| defined(__ARM_ARCH_6M__) || \
defined(__ARM_ARCH_6Z__)|| defined(__ARM_ARCH_6ZK__) || \
defined(__ARM_ARCH_6T2__)
# define __ARM_ARCH__ 6
# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \
defined(__ARM_ARCH_5E__)|| defined(__ARM_ARCH_5TE__) || \
defined(__ARM_ARCH_5TEJ__)
# define __ARM_ARCH__ 5
# elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
# define __ARM_ARCH__ 4
# else
# error "unsupported ARM architecture"
# endif
# endif
#endif
#ifdef OPENSSL_FIPSCANISTER
#include <openssl/fipssyms.h>
#endif
#if !__ASSEMBLER__
extern unsigned int OPENSSL_armcap_P;
#define ARMV7_NEON (1<<0)
#define ARMV7_TICK (1<<1)
#endif
#endif

View File

@ -5,6 +5,7 @@
#include <stdlib.h>
#include <time.h>
#include <opusfile.h>
#include <math.h>
#include "utils.h"
typedef struct {
@ -504,7 +505,7 @@ int writeFrame(uint8_t *framePcmBytes, unsigned int frameByteCount) {
return 1;
}
JNIEXPORT int Java_org_telegram_android_MediaController_startRecord(JNIEnv *env, jclass class, jstring path) {
JNIEXPORT int Java_org_telegram_messenger_MediaController_startRecord(JNIEnv *env, jclass class, jstring path) {
const char *pathStr = (*env)->GetStringUTFChars(env, path, 0);
int result = initRecorder(pathStr);
@ -516,12 +517,12 @@ JNIEXPORT int Java_org_telegram_android_MediaController_startRecord(JNIEnv *env,
return result;
}
JNIEXPORT int Java_org_telegram_android_MediaController_writeFrame(JNIEnv *env, jclass class, jobject frame, jint len) {
JNIEXPORT int Java_org_telegram_messenger_MediaController_writeFrame(JNIEnv *env, jclass class, jobject frame, jint len) {
jbyte *frameBytes = (*env)->GetDirectBufferAddress(env, frame);
return writeFrame(frameBytes, len);
}
JNIEXPORT void Java_org_telegram_android_MediaController_stopRecord(JNIEnv *env, jclass class) {
JNIEXPORT void Java_org_telegram_messenger_MediaController_stopRecord(JNIEnv *env, jclass class) {
cleanupRecorder();
}
@ -618,22 +619,22 @@ void fillBuffer(uint8_t *buffer, int capacity, int *args) {
}
}
JNIEXPORT jlong Java_org_telegram_android_MediaController_getTotalPcmDuration(JNIEnv *env, jclass class) {
JNIEXPORT jlong Java_org_telegram_messenger_MediaController_getTotalPcmDuration(JNIEnv *env, jclass class) {
return _totalPcmDuration;
}
JNIEXPORT void Java_org_telegram_android_MediaController_readOpusFile(JNIEnv *env, jclass class, jobject buffer, jint capacity, jintArray args) {
JNIEXPORT void Java_org_telegram_messenger_MediaController_readOpusFile(JNIEnv *env, jclass class, jobject buffer, jint capacity, jintArray args) {
jint *argsArr = (*env)->GetIntArrayElements(env, args, 0);
jbyte *bufferBytes = (*env)->GetDirectBufferAddress(env, buffer);
fillBuffer(bufferBytes, capacity, argsArr);
(*env)->ReleaseIntArrayElements(env, args, argsArr, 0);
}
JNIEXPORT int Java_org_telegram_android_MediaController_seekOpusFile(JNIEnv *env, jclass class, jfloat position) {
JNIEXPORT int Java_org_telegram_messenger_MediaController_seekOpusFile(JNIEnv *env, jclass class, jfloat position) {
return seekPlayer(position);
}
JNIEXPORT int Java_org_telegram_android_MediaController_openOpusFile(JNIEnv *env, jclass class, jstring path) {
JNIEXPORT int Java_org_telegram_messenger_MediaController_openOpusFile(JNIEnv *env, jclass class, jstring path) {
const char *pathStr = (*env)->GetStringUTFChars(env, path, 0);
int result = initPlayer(pathStr);
@ -645,11 +646,11 @@ JNIEXPORT int Java_org_telegram_android_MediaController_openOpusFile(JNIEnv *env
return result;
}
JNIEXPORT void Java_org_telegram_android_MediaController_closeOpusFile(JNIEnv *env, jclass class) {
JNIEXPORT void Java_org_telegram_messenger_MediaController_closeOpusFile(JNIEnv *env, jclass class) {
cleanupPlayer();
}
JNIEXPORT int Java_org_telegram_android_MediaController_isOpusFile(JNIEnv *env, jclass class, jstring path) {
JNIEXPORT int Java_org_telegram_messenger_MediaController_isOpusFile(JNIEnv *env, jclass class, jstring path) {
const char *pathStr = (*env)->GetStringUTFChars(env, path, 0);
int result = 0;
@ -663,6 +664,155 @@ JNIEXPORT int Java_org_telegram_android_MediaController_isOpusFile(JNIEnv *env,
result = error == OPUS_OK;
}
if (pathStr != 0) {
(*env)->ReleaseStringUTFChars(env, path, pathStr);
}
return result;
}
static inline void set_bits(uint8_t *bytes, int32_t bitOffset, int32_t value) {
bytes += bitOffset / 8;
bitOffset %= 8;
*((int32_t *) bytes) |= (value << bitOffset);
}
JNIEXPORT jbyteArray Java_org_telegram_messenger_MediaController_getWaveform2(JNIEnv *env, jclass class, jshortArray array, jint length) {
jshort *sampleBuffer = (*env)->GetShortArrayElements(env, array, 0);
jbyteArray result = 0;
int32_t resultSamples = 100;
uint16_t *samples = malloc(100 * 2);
uint64_t sampleIndex = 0;
uint16_t peakSample = 0;
int32_t sampleRate = (int32_t) max(1, length / resultSamples);
int index = 0;
for (int i = 0; i < length; i++) {
uint16_t sample = (uint16_t) abs(sampleBuffer[i]);
if (sample > peakSample) {
peakSample = sample;
}
if (sampleIndex++ % sampleRate == 0) {
if (index < resultSamples) {
samples[index++] = peakSample;
}
peakSample = 0;
}
}
int64_t sumSamples = 0;
for (int i = 0; i < resultSamples; i++) {
sumSamples += samples[i];
}
uint16_t peak = (uint16_t) (sumSamples * 1.8f / resultSamples);
if (peak < 2500) {
peak = 2500;
}
for (int i = 0; i < resultSamples; i++) {
uint16_t sample = (uint16_t) ((int64_t) samples[i]);
if (sample > peak) {
samples[i] = peak;
}
}
(*env)->ReleaseShortArrayElements(env, array, sampleBuffer, 0);
int bitstreamLength = (resultSamples * 5) / 8 + (((resultSamples * 5) % 8) == 0 ? 0 : 1);
result = (*env)->NewByteArray(env, bitstreamLength);
jbyte *bytes = (*env)->GetByteArrayElements(env, result, NULL);
for (int i = 0; i < resultSamples; i++) {
int32_t value = min(31, abs((int32_t) samples[i]) * 31 / peak);
set_bits(bytes, i * 5, value & 31);
}
(*env)->ReleaseByteArrayElements(env, result, bytes, JNI_COMMIT);
free(samples);
return result;
}
int16_t *sampleBuffer = NULL;
JNIEXPORT jbyteArray Java_org_telegram_messenger_MediaController_getWaveform(JNIEnv *env, jclass class, jstring path) {
const char *pathStr = (*env)->GetStringUTFChars(env, path, 0);
jbyteArray result = 0;
int error = OPUS_OK;
OggOpusFile *opusFile = op_open_file(pathStr, &error);
if (opusFile != NULL && error == OPUS_OK) {
int64_t totalSamples = op_pcm_total(opusFile, -1);
int32_t resultSamples = 100;
int32_t sampleRate = (int32_t) max(1, totalSamples / resultSamples);
uint16_t *samples = malloc(100 * 2);
int bufferSize = 1024 * 128;
if (sampleBuffer == NULL) {
sampleBuffer = malloc(bufferSize);
}
uint64_t sampleIndex = 0;
uint16_t peakSample = 0;
int index = 0;
while (1) {
int readSamples = op_read(opusFile, sampleBuffer, bufferSize / 2, NULL);
for (int i = 0; i < readSamples; i++) {
uint16_t sample = (uint16_t) abs(sampleBuffer[i]);
if (sample > peakSample) {
peakSample = sample;
}
if (sampleIndex++ % sampleRate == 0) {
if (index < resultSamples) {
samples[index++] = peakSample;
}
peakSample = 0;
}
}
if (readSamples == 0) {
break;
}
}
int64_t sumSamples = 0;
for (int i = 0; i < resultSamples; i++) {
sumSamples += samples[i];
}
uint16_t peak = (uint16_t) (sumSamples * 1.8f / resultSamples);
if (peak < 2500) {
peak = 2500;
}
for (int i = 0; i < resultSamples; i++) {
uint16_t sample = (uint16_t) ((int64_t) samples[i]);
if (sample > peak) {
samples[i] = peak;
}
}
//free(sampleBuffer);
op_free(opusFile);
int bitstreamLength = (resultSamples * 5) / 8 + (((resultSamples * 5) % 8) == 0 ? 0 : 1);
result = (*env)->NewByteArray(env, bitstreamLength);
jbyte *bytes = (*env)->GetByteArrayElements(env, result, NULL);
for (int i = 0; i < resultSamples; i++) {
int32_t value = min(31, abs((int32_t) samples[i]) * 31 / peak);
set_bits(bytes, i * 5, value & 31);
}
(*env)->ReleaseByteArrayElements(env, result, bytes, JNI_COMMIT);
free(samples);
}
if (pathStr != 0) {
(*env)->ReleaseStringUTFChars(env, path, pathStr);
}

View File

@ -0,0 +1,185 @@
BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL
licensing. Files that are completely new have a Google copyright and an ISC
license. This license is reproduced at the bottom of this file.
Contributors to BoringSSL are required to follow the CLA rules for Chromium:
https://cla.developers.google.com/clas
Some files from Intel are under yet another license, which is also included
underneath.
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the
OpenSSL License and the original SSLeay license apply to the toolkit. See below
for the actual license texts. Actually both licenses are BSD-style Open Source
licenses. In case of any license issues related to OpenSSL please contact
openssl-core@openssl.org.
OpenSSL License
---------------
/* ====================================================================
* Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
Original SSLeay License
-----------------------
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
ISC license used for completely new code in BoringSSL:
/* Copyright (c) 2015, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
Some files from Intel carry the following license:
# Copyright (c) 2012, Intel Corporation
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the
# distribution.
#
# * Neither the name of the Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
#
# THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,10 @@
cmake, ninja, go are required
cmake -DANDROID_NATIVE_API_LEVEL=android-8 \
-DANDROID_ABI=x86 \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_NDK=/Applications/sdk/ndk-bundle/ \
-DCMAKE_TOOLCHAIN_FILE=../util/android-cmake/android.toolchain.cmake \
-DANDROID_NATIVE_API_LEVEL=16 \
-GNinja ..
cmake --build .

View File

@ -0,0 +1 @@
*.txt~

View File

@ -0,0 +1,197 @@
include_directories(. ../include)
if(APPLE)
if (${ARCH} STREQUAL "x86")
set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2")
endif()
set(PERLASM_STYLE macosx)
set(ASM_EXT S)
enable_language(ASM)
elseif(UNIX)
if (${ARCH} STREQUAL "aarch64")
# The "armx" Perl scripts look for "64" in the style argument
# in order to decide whether to generate 32- or 64-bit asm.
set(PERLASM_STYLE linux64)
elseif (${ARCH} STREQUAL "arm")
set(PERLASM_STYLE linux32)
elseif (${ARCH} STREQUAL "x86")
set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2")
set(PERLASM_STYLE elf)
else()
set(PERLASM_STYLE elf)
endif()
set(ASM_EXT S)
enable_language(ASM)
else()
if (CMAKE_CL_64)
message("Using nasm")
set(PERLASM_STYLE nasm)
else()
message("Using win32n")
set(PERLASM_STYLE win32n)
set(PERLASM_FLAGS "-DOPENSSL_IA32_SSE2")
endif()
# On Windows, we use the NASM output, specifically built with Yasm.
set(ASM_EXT asm)
enable_language(ASM_NASM)
endif()
function(perlasm dest src)
add_custom_command(
OUTPUT ${dest}
COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${PERLASM_STYLE} ${PERLASM_FLAGS} ${ARGN} > ${dest}
DEPENDS
${src}
${PROJECT_SOURCE_DIR}/crypto/perlasm/arm-xlate.pl
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86_64-xlate.pl
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86asm.pl
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86gas.pl
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86masm.pl
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86nasm.pl
WORKING_DIRECTORY .
)
endfunction()
if (${ARCH} STREQUAL "x86_64")
set(
CRYPTO_ARCH_SOURCES
cpu-intel.c
)
endif()
if (${ARCH} STREQUAL "x86")
set(
CRYPTO_ARCH_SOURCES
cpu-intel.c
)
endif()
if (${ARCH} STREQUAL "arm")
set(
CRYPTO_ARCH_SOURCES
cpu-arm.c
cpu-arm-asm.S
)
endif()
if (${ARCH} STREQUAL "aarch64")
set(
CRYPTO_ARCH_SOURCES
cpu-arm.c
)
endif()
# Level 0.1 - depends on nothing outside this set.
add_subdirectory(stack)
add_subdirectory(lhash)
add_subdirectory(err)
add_subdirectory(buf)
add_subdirectory(base64)
add_subdirectory(bytestring)
# Level 0.2 - depends on nothing but itself
add_subdirectory(sha)
add_subdirectory(md5)
add_subdirectory(modes)
add_subdirectory(aes)
add_subdirectory(des)
add_subdirectory(rc4)
add_subdirectory(conf)
add_subdirectory(chacha)
add_subdirectory(poly1305)
# Level 1, depends only on 0.*
add_subdirectory(digest)
add_subdirectory(cipher)
add_subdirectory(rand)
add_subdirectory(bio)
add_subdirectory(bn)
add_subdirectory(obj)
add_subdirectory(asn1)
# Level 2
add_subdirectory(engine)
add_subdirectory(dh)
add_subdirectory(dsa)
add_subdirectory(rsa)
add_subdirectory(ec)
add_subdirectory(ecdh)
add_subdirectory(ecdsa)
add_subdirectory(hmac)
# Level 3
add_subdirectory(cmac)
add_subdirectory(evp)
add_subdirectory(hkdf)
add_subdirectory(pem)
add_subdirectory(x509)
add_subdirectory(x509v3)
# Level 4
add_subdirectory(pkcs8)
add_library(
crypto
crypto.c
directory_posix.c
directory_win.c
ex_data.c
mem.c
refcount_c11.c
refcount_lock.c
thread.c
thread_none.c
thread_pthread.c
thread_win.c
time_support.c
${CRYPTO_ARCH_SOURCES}
$<TARGET_OBJECTS:stack>
$<TARGET_OBJECTS:lhash>
$<TARGET_OBJECTS:err>
$<TARGET_OBJECTS:base64>
$<TARGET_OBJECTS:bytestring>
$<TARGET_OBJECTS:sha>
$<TARGET_OBJECTS:md5>
$<TARGET_OBJECTS:digest>
$<TARGET_OBJECTS:cipher>
$<TARGET_OBJECTS:modes>
$<TARGET_OBJECTS:aes>
$<TARGET_OBJECTS:des>
$<TARGET_OBJECTS:rc4>
$<TARGET_OBJECTS:conf>
$<TARGET_OBJECTS:chacha>
$<TARGET_OBJECTS:poly1305>
$<TARGET_OBJECTS:buf>
$<TARGET_OBJECTS:bn>
$<TARGET_OBJECTS:bio>
$<TARGET_OBJECTS:rand>
$<TARGET_OBJECTS:obj>
$<TARGET_OBJECTS:asn1>
$<TARGET_OBJECTS:engine>
$<TARGET_OBJECTS:dh>
$<TARGET_OBJECTS:dsa>
$<TARGET_OBJECTS:rsa>
$<TARGET_OBJECTS:ec>
$<TARGET_OBJECTS:ecdh>
$<TARGET_OBJECTS:ecdsa>
$<TARGET_OBJECTS:hmac>
$<TARGET_OBJECTS:cmac>
$<TARGET_OBJECTS:evp>
$<TARGET_OBJECTS:hkdf>
$<TARGET_OBJECTS:pem>
$<TARGET_OBJECTS:x509>
$<TARGET_OBJECTS:x509v3>
$<TARGET_OBJECTS:pkcs8>
)
if(NOT MSVC AND NOT ANDROID)
target_link_libraries(crypto pthread)
endif()

View File

@ -0,0 +1,63 @@
include_directories(. .. ../../include)
if (${ARCH} STREQUAL "x86_64")
set(
AES_ARCH_SOURCES
aes-x86_64.${ASM_EXT}
aesni-x86_64.${ASM_EXT}
bsaes-x86_64.${ASM_EXT}
vpaes-x86_64.${ASM_EXT}
)
endif()
if (${ARCH} STREQUAL "x86")
set(
AES_ARCH_SOURCES
aes-586.${ASM_EXT}
vpaes-x86.${ASM_EXT}
aesni-x86.${ASM_EXT}
)
endif()
if (${ARCH} STREQUAL "arm")
set(
AES_ARCH_SOURCES
aes-armv4.${ASM_EXT}
bsaes-armv7.${ASM_EXT}
aesv8-armx.${ASM_EXT}
)
endif()
if (${ARCH} STREQUAL "aarch64")
set(
AES_ARCH_SOURCES
aesv8-armx.${ASM_EXT}
)
endif()
add_library(
aes
OBJECT
aes.c
aes_ige.c
mode_wrappers.c
${AES_ARCH_SOURCES}
)
perlasm(aes-x86_64.${ASM_EXT} asm/aes-x86_64.pl)
perlasm(aesni-x86_64.${ASM_EXT} asm/aesni-x86_64.pl)
perlasm(bsaes-x86_64.${ASM_EXT} asm/bsaes-x86_64.pl)
perlasm(vpaes-x86_64.${ASM_EXT} asm/vpaes-x86_64.pl)
perlasm(aes-586.${ASM_EXT} asm/aes-586.pl)
perlasm(vpaes-x86.${ASM_EXT} asm/vpaes-x86.pl)
perlasm(aesni-x86.${ASM_EXT} asm/aesni-x86.pl)
perlasm(aes-armv4.${ASM_EXT} asm/aes-armv4.pl)
perlasm(bsaes-armv7.${ASM_EXT} asm/bsaes-armv7.pl)
perlasm(aesv8-armx.${ASM_EXT} asm/aesv8-armx.pl)

File diff suppressed because it is too large Load Diff

View File

@ -49,12 +49,10 @@
*
*/
//#include "cryptlib.h"
#include "aes.h"
#include "aes_locl.h"
#include <openssl/aes.h>
#include <assert.h>
#define OPENSSL_assert assert
#include <memory.h>
#include <string.h>
#define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long))
typedef struct {
@ -85,9 +83,9 @@ void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
size_t n;
size_t len = length;
OPENSSL_assert(in && out && key && ivec);
OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));
OPENSSL_assert((length%AES_BLOCK_SIZE) == 0);
assert(in && out && key && ivec);
assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));
assert((length%AES_BLOCK_SIZE) == 0);
len = length / AES_BLOCK_SIZE;
@ -226,9 +224,9 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
const unsigned char *iv;
const unsigned char *iv2;
OPENSSL_assert(in && out && key && ivec);
OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));
OPENSSL_assert((length%AES_BLOCK_SIZE) == 0);
assert(in && out && key && ivec);
assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));
assert((length%AES_BLOCK_SIZE) == 0);
if (AES_ENCRYPT == enc)
{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,903 @@
#!/usr/bin/env perl
######################################################################
## Constant-time SSSE3 AES core implementation.
## version 0.1
##
## By Mike Hamburg (Stanford University), 2009
## Public domain.
##
## For details see http://shiftleft.org/papers/vector_aes/ and
## http://crypto.stanford.edu/vpaes/.
######################################################################
# September 2011.
#
# Port vpaes-x86_64.pl as 32-bit "almost" drop-in replacement for
# aes-586.pl. "Almost" refers to the fact that AES_cbc_encrypt
# doesn't handle partial vectors (doesn't have to if called from
# EVP only). "Drop-in" implies that this module doesn't share key
# schedule structure with the original nor does it make assumption
# about its alignment...
#
# Performance summary. aes-586.pl column lists large-block CBC
# encrypt/decrypt/with-hyper-threading-off(*) results in cycles per
# byte processed with 128-bit key, and vpaes-x86.pl column - [also
# large-block CBC] encrypt/decrypt.
#
# aes-586.pl vpaes-x86.pl
#
# Core 2(**) 28.1/41.4/18.3 21.9/25.2(***)
# Nehalem 27.9/40.4/18.1 10.2/11.9
# Atom 70.7/92.1/60.1 61.1/75.4(***)
# Silvermont 45.4/62.9/24.1 49.2/61.1(***)
#
# (*) "Hyper-threading" in the context refers rather to cache shared
# among multiple cores, than to specifically Intel HTT. As vast
# majority of contemporary cores share cache, slower code path
# is common place. In other words "with-hyper-threading-off"
# results are presented mostly for reference purposes.
#
# (**) "Core 2" refers to initial 65nm design, a.k.a. Conroe.
#
# (***) Less impressive improvement on Core 2 and Atom is due to slow
# pshufb, yet it's respectable +28%/64% improvement on Core 2
# and +15% on Atom (as implied, over "hyper-threading-safe"
# code path).
#
# <appro@openssl.org>
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
&asm_init($ARGV[0],"vpaes-x86.pl",$x86only = $ARGV[$#ARGV] eq "386");
$PREFIX="vpaes";
my ($round, $base, $magic, $key, $const, $inp, $out)=
("eax", "ebx", "ecx", "edx","ebp", "esi","edi");
&static_label("_vpaes_consts");
&static_label("_vpaes_schedule_low_round");
&set_label("_vpaes_consts",64);
$k_inv=-0x30; # inv, inva
&data_word(0x0D080180,0x0E05060F,0x0A0B0C02,0x04070309);
&data_word(0x0F0B0780,0x01040A06,0x02050809,0x030D0E0C);
$k_s0F=-0x10; # s0F
&data_word(0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F);
$k_ipt=0x00; # input transform (lo, hi)
&data_word(0x5A2A7000,0xC2B2E898,0x52227808,0xCABAE090);
&data_word(0x317C4D00,0x4C01307D,0xB0FDCC81,0xCD80B1FC);
$k_sb1=0x20; # sb1u, sb1t
&data_word(0xCB503E00,0xB19BE18F,0x142AF544,0xA5DF7A6E);
&data_word(0xFAE22300,0x3618D415,0x0D2ED9EF,0x3BF7CCC1);
$k_sb2=0x40; # sb2u, sb2t
&data_word(0x0B712400,0xE27A93C6,0xBC982FCD,0x5EB7E955);
&data_word(0x0AE12900,0x69EB8840,0xAB82234A,0xC2A163C8);
$k_sbo=0x60; # sbou, sbot
&data_word(0x6FBDC700,0xD0D26D17,0xC502A878,0x15AABF7A);
&data_word(0x5FBB6A00,0xCFE474A5,0x412B35FA,0x8E1E90D1);
$k_mc_forward=0x80; # mc_forward
&data_word(0x00030201,0x04070605,0x080B0A09,0x0C0F0E0D);
&data_word(0x04070605,0x080B0A09,0x0C0F0E0D,0x00030201);
&data_word(0x080B0A09,0x0C0F0E0D,0x00030201,0x04070605);
&data_word(0x0C0F0E0D,0x00030201,0x04070605,0x080B0A09);
$k_mc_backward=0xc0; # mc_backward
&data_word(0x02010003,0x06050407,0x0A09080B,0x0E0D0C0F);
&data_word(0x0E0D0C0F,0x02010003,0x06050407,0x0A09080B);
&data_word(0x0A09080B,0x0E0D0C0F,0x02010003,0x06050407);
&data_word(0x06050407,0x0A09080B,0x0E0D0C0F,0x02010003);
$k_sr=0x100; # sr
&data_word(0x03020100,0x07060504,0x0B0A0908,0x0F0E0D0C);
&data_word(0x0F0A0500,0x030E0904,0x07020D08,0x0B06010C);
&data_word(0x0B020900,0x0F060D04,0x030A0108,0x070E050C);
&data_word(0x070A0D00,0x0B0E0104,0x0F020508,0x0306090C);
$k_rcon=0x140; # rcon
&data_word(0xAF9DEEB6,0x1F8391B9,0x4D7C7D81,0x702A9808);
$k_s63=0x150; # s63: all equal to 0x63 transformed
&data_word(0x5B5B5B5B,0x5B5B5B5B,0x5B5B5B5B,0x5B5B5B5B);
$k_opt=0x160; # output transform
&data_word(0xD6B66000,0xFF9F4929,0xDEBE6808,0xF7974121);
&data_word(0x50BCEC00,0x01EDBD51,0xB05C0CE0,0xE10D5DB1);
$k_deskew=0x180; # deskew tables: inverts the sbox's "skew"
&data_word(0x47A4E300,0x07E4A340,0x5DBEF91A,0x1DFEB95A);
&data_word(0x83EA6900,0x5F36B5DC,0xF49D1E77,0x2841C2AB);
##
## Decryption stuff
## Key schedule constants
##
$k_dksd=0x1a0; # decryption key schedule: invskew x*D
&data_word(0xA3E44700,0xFEB91A5D,0x5A1DBEF9,0x0740E3A4);
&data_word(0xB5368300,0x41C277F4,0xAB289D1E,0x5FDC69EA);
$k_dksb=0x1c0; # decryption key schedule: invskew x*B
&data_word(0x8550D500,0x9A4FCA1F,0x1CC94C99,0x03D65386);
&data_word(0xB6FC4A00,0x115BEDA7,0x7E3482C8,0xD993256F);
$k_dkse=0x1e0; # decryption key schedule: invskew x*E + 0x63
&data_word(0x1FC9D600,0xD5031CCA,0x994F5086,0x53859A4C);
&data_word(0x4FDC7BE8,0xA2319605,0x20B31487,0xCD5EF96A);
$k_dks9=0x200; # decryption key schedule: invskew x*9
&data_word(0x7ED9A700,0xB6116FC8,0x82255BFC,0x4AED9334);
&data_word(0x27143300,0x45765162,0xE9DAFDCE,0x8BB89FAC);
##
## Decryption stuff
## Round function constants
##
$k_dipt=0x220; # decryption input transform
&data_word(0x0B545F00,0x0F505B04,0x114E451A,0x154A411E);
&data_word(0x60056500,0x86E383E6,0xF491F194,0x12771772);
$k_dsb9=0x240; # decryption sbox output *9*u, *9*t
&data_word(0x9A86D600,0x851C0353,0x4F994CC9,0xCAD51F50);
&data_word(0xECD74900,0xC03B1789,0xB2FBA565,0x725E2C9E);
$k_dsbd=0x260; # decryption sbox output *D*u, *D*t
&data_word(0xE6B1A200,0x7D57CCDF,0x882A4439,0xF56E9B13);
&data_word(0x24C6CB00,0x3CE2FAF7,0x15DEEFD3,0x2931180D);
$k_dsbb=0x280; # decryption sbox output *B*u, *B*t
&data_word(0x96B44200,0xD0226492,0xB0F2D404,0x602646F6);
&data_word(0xCD596700,0xC19498A6,0x3255AA6B,0xF3FF0C3E);
$k_dsbe=0x2a0; # decryption sbox output *E*u, *E*t
&data_word(0x26D4D000,0x46F29296,0x64B4F6B0,0x22426004);
&data_word(0xFFAAC100,0x0C55A6CD,0x98593E32,0x9467F36B);
$k_dsbo=0x2c0; # decryption sbox final output
&data_word(0x7EF94000,0x1387EA53,0xD4943E2D,0xC7AA6DB9);
&data_word(0x93441D00,0x12D7560F,0xD8C58E9C,0xCA4B8159);
&asciz ("Vector Permutation AES for x86/SSSE3, Mike Hamburg (Stanford University)");
&align (64);
&function_begin_B("_vpaes_preheat");
&add ($const,&DWP(0,"esp"));
&movdqa ("xmm7",&QWP($k_inv,$const));
&movdqa ("xmm6",&QWP($k_s0F,$const));
&ret ();
&function_end_B("_vpaes_preheat");
##
## _aes_encrypt_core
##
## AES-encrypt %xmm0.
##
## Inputs:
## %xmm0 = input
## %xmm6-%xmm7 as in _vpaes_preheat
## (%edx) = scheduled keys
##
## Output in %xmm0
## Clobbers %xmm1-%xmm5, %eax, %ebx, %ecx, %edx
##
##
&function_begin_B("_vpaes_encrypt_core");
&mov ($magic,16);
&mov ($round,&DWP(240,$key));
&movdqa ("xmm1","xmm6")
&movdqa ("xmm2",&QWP($k_ipt,$const));
&pandn ("xmm1","xmm0");
&pand ("xmm0","xmm6");
&movdqu ("xmm5",&QWP(0,$key));
&pshufb ("xmm2","xmm0");
&movdqa ("xmm0",&QWP($k_ipt+16,$const));
&pxor ("xmm2","xmm5");
&psrld ("xmm1",4);
&add ($key,16);
&pshufb ("xmm0","xmm1");
&lea ($base,&DWP($k_mc_backward,$const));
&pxor ("xmm0","xmm2");
&jmp (&label("enc_entry"));
&set_label("enc_loop",16);
# middle of middle round
&movdqa ("xmm4",&QWP($k_sb1,$const)); # 4 : sb1u
&movdqa ("xmm0",&QWP($k_sb1+16,$const));# 0 : sb1t
&pshufb ("xmm4","xmm2"); # 4 = sb1u
&pshufb ("xmm0","xmm3"); # 0 = sb1t
&pxor ("xmm4","xmm5"); # 4 = sb1u + k
&movdqa ("xmm5",&QWP($k_sb2,$const)); # 4 : sb2u
&pxor ("xmm0","xmm4"); # 0 = A
&movdqa ("xmm1",&QWP(-0x40,$base,$magic));# .Lk_mc_forward[]
&pshufb ("xmm5","xmm2"); # 4 = sb2u
&movdqa ("xmm2",&QWP($k_sb2+16,$const));# 2 : sb2t
&movdqa ("xmm4",&QWP(0,$base,$magic)); # .Lk_mc_backward[]
&pshufb ("xmm2","xmm3"); # 2 = sb2t
&movdqa ("xmm3","xmm0"); # 3 = A
&pxor ("xmm2","xmm5"); # 2 = 2A
&pshufb ("xmm0","xmm1"); # 0 = B
&add ($key,16); # next key
&pxor ("xmm0","xmm2"); # 0 = 2A+B
&pshufb ("xmm3","xmm4"); # 3 = D
&add ($magic,16); # next mc
&pxor ("xmm3","xmm0"); # 3 = 2A+B+D
&pshufb ("xmm0","xmm1"); # 0 = 2B+C
&and ($magic,0x30); # ... mod 4
&sub ($round,1); # nr--
&pxor ("xmm0","xmm3"); # 0 = 2A+3B+C+D
&set_label("enc_entry");
# top of round
&movdqa ("xmm1","xmm6"); # 1 : i
&movdqa ("xmm5",&QWP($k_inv+16,$const));# 2 : a/k
&pandn ("xmm1","xmm0"); # 1 = i<<4
&psrld ("xmm1",4); # 1 = i
&pand ("xmm0","xmm6"); # 0 = k
&pshufb ("xmm5","xmm0"); # 2 = a/k
&movdqa ("xmm3","xmm7"); # 3 : 1/i
&pxor ("xmm0","xmm1"); # 0 = j
&pshufb ("xmm3","xmm1"); # 3 = 1/i
&movdqa ("xmm4","xmm7"); # 4 : 1/j
&pxor ("xmm3","xmm5"); # 3 = iak = 1/i + a/k
&pshufb ("xmm4","xmm0"); # 4 = 1/j
&movdqa ("xmm2","xmm7"); # 2 : 1/iak
&pxor ("xmm4","xmm5"); # 4 = jak = 1/j + a/k
&pshufb ("xmm2","xmm3"); # 2 = 1/iak
&movdqa ("xmm3","xmm7"); # 3 : 1/jak
&pxor ("xmm2","xmm0"); # 2 = io
&pshufb ("xmm3","xmm4"); # 3 = 1/jak
&movdqu ("xmm5",&QWP(0,$key));
&pxor ("xmm3","xmm1"); # 3 = jo
&jnz (&label("enc_loop"));
# middle of last round
&movdqa ("xmm4",&QWP($k_sbo,$const)); # 3 : sbou .Lk_sbo
&movdqa ("xmm0",&QWP($k_sbo+16,$const));# 3 : sbot .Lk_sbo+16
&pshufb ("xmm4","xmm2"); # 4 = sbou
&pxor ("xmm4","xmm5"); # 4 = sb1u + k
&pshufb ("xmm0","xmm3"); # 0 = sb1t
&movdqa ("xmm1",&QWP(0x40,$base,$magic));# .Lk_sr[]
&pxor ("xmm0","xmm4"); # 0 = A
&pshufb ("xmm0","xmm1");
&ret ();
&function_end_B("_vpaes_encrypt_core");
##
## Decryption core
##
## Same API as encryption core.
##
&function_begin_B("_vpaes_decrypt_core");
&lea ($base,&DWP($k_dsbd,$const));
&mov ($round,&DWP(240,$key));
&movdqa ("xmm1","xmm6");
&movdqa ("xmm2",&QWP($k_dipt-$k_dsbd,$base));
&pandn ("xmm1","xmm0");
&mov ($magic,$round);
&psrld ("xmm1",4)
&movdqu ("xmm5",&QWP(0,$key));
&shl ($magic,4);
&pand ("xmm0","xmm6");
&pshufb ("xmm2","xmm0");
&movdqa ("xmm0",&QWP($k_dipt-$k_dsbd+16,$base));
&xor ($magic,0x30);
&pshufb ("xmm0","xmm1");
&and ($magic,0x30);
&pxor ("xmm2","xmm5");
&movdqa ("xmm5",&QWP($k_mc_forward+48,$const));
&pxor ("xmm0","xmm2");
&add ($key,16);
&lea ($magic,&DWP($k_sr-$k_dsbd,$base,$magic));
&jmp (&label("dec_entry"));
&set_label("dec_loop",16);
##
## Inverse mix columns
##
&movdqa ("xmm4",&QWP(-0x20,$base)); # 4 : sb9u
&movdqa ("xmm1",&QWP(-0x10,$base)); # 0 : sb9t
&pshufb ("xmm4","xmm2"); # 4 = sb9u
&pshufb ("xmm1","xmm3"); # 0 = sb9t
&pxor ("xmm0","xmm4");
&movdqa ("xmm4",&QWP(0,$base)); # 4 : sbdu
&pxor ("xmm0","xmm1"); # 0 = ch
&movdqa ("xmm1",&QWP(0x10,$base)); # 0 : sbdt
&pshufb ("xmm4","xmm2"); # 4 = sbdu
&pshufb ("xmm0","xmm5"); # MC ch
&pshufb ("xmm1","xmm3"); # 0 = sbdt
&pxor ("xmm0","xmm4"); # 4 = ch
&movdqa ("xmm4",&QWP(0x20,$base)); # 4 : sbbu
&pxor ("xmm0","xmm1"); # 0 = ch
&movdqa ("xmm1",&QWP(0x30,$base)); # 0 : sbbt
&pshufb ("xmm4","xmm2"); # 4 = sbbu
&pshufb ("xmm0","xmm5"); # MC ch
&pshufb ("xmm1","xmm3"); # 0 = sbbt
&pxor ("xmm0","xmm4"); # 4 = ch
&movdqa ("xmm4",&QWP(0x40,$base)); # 4 : sbeu
&pxor ("xmm0","xmm1"); # 0 = ch
&movdqa ("xmm1",&QWP(0x50,$base)); # 0 : sbet
&pshufb ("xmm4","xmm2"); # 4 = sbeu
&pshufb ("xmm0","xmm5"); # MC ch
&pshufb ("xmm1","xmm3"); # 0 = sbet
&pxor ("xmm0","xmm4"); # 4 = ch
&add ($key,16); # next round key
&palignr("xmm5","xmm5",12);
&pxor ("xmm0","xmm1"); # 0 = ch
&sub ($round,1); # nr--
&set_label("dec_entry");
# top of round
&movdqa ("xmm1","xmm6"); # 1 : i
&movdqa ("xmm2",&QWP($k_inv+16,$const));# 2 : a/k
&pandn ("xmm1","xmm0"); # 1 = i<<4
&pand ("xmm0","xmm6"); # 0 = k
&psrld ("xmm1",4); # 1 = i
&pshufb ("xmm2","xmm0"); # 2 = a/k
&movdqa ("xmm3","xmm7"); # 3 : 1/i
&pxor ("xmm0","xmm1"); # 0 = j
&pshufb ("xmm3","xmm1"); # 3 = 1/i
&movdqa ("xmm4","xmm7"); # 4 : 1/j
&pxor ("xmm3","xmm2"); # 3 = iak = 1/i + a/k
&pshufb ("xmm4","xmm0"); # 4 = 1/j
&pxor ("xmm4","xmm2"); # 4 = jak = 1/j + a/k
&movdqa ("xmm2","xmm7"); # 2 : 1/iak
&pshufb ("xmm2","xmm3"); # 2 = 1/iak
&movdqa ("xmm3","xmm7"); # 3 : 1/jak
&pxor ("xmm2","xmm0"); # 2 = io
&pshufb ("xmm3","xmm4"); # 3 = 1/jak
&movdqu ("xmm0",&QWP(0,$key));
&pxor ("xmm3","xmm1"); # 3 = jo
&jnz (&label("dec_loop"));
# middle of last round
&movdqa ("xmm4",&QWP(0x60,$base)); # 3 : sbou
&pshufb ("xmm4","xmm2"); # 4 = sbou
&pxor ("xmm4","xmm0"); # 4 = sb1u + k
&movdqa ("xmm0",&QWP(0x70,$base)); # 0 : sbot
&movdqa ("xmm2",&QWP(0,$magic));
&pshufb ("xmm0","xmm3"); # 0 = sb1t
&pxor ("xmm0","xmm4"); # 0 = A
&pshufb ("xmm0","xmm2");
&ret ();
&function_end_B("_vpaes_decrypt_core");
########################################################
## ##
## AES key schedule ##
## ##
########################################################
&function_begin_B("_vpaes_schedule_core");
&add ($const,&DWP(0,"esp"));
&movdqu ("xmm0",&QWP(0,$inp)); # load key (unaligned)
&movdqa ("xmm2",&QWP($k_rcon,$const)); # load rcon
# input transform
&movdqa ("xmm3","xmm0");
&lea ($base,&DWP($k_ipt,$const));
&movdqa (&QWP(4,"esp"),"xmm2"); # xmm8
&call ("_vpaes_schedule_transform");
&movdqa ("xmm7","xmm0");
&test ($out,$out);
&jnz (&label("schedule_am_decrypting"));
# encrypting, output zeroth round key after transform
&movdqu (&QWP(0,$key),"xmm0");
&jmp (&label("schedule_go"));
&set_label("schedule_am_decrypting");
# decrypting, output zeroth round key after shiftrows
&movdqa ("xmm1",&QWP($k_sr,$const,$magic));
&pshufb ("xmm3","xmm1");
&movdqu (&QWP(0,$key),"xmm3");
&xor ($magic,0x30);
&set_label("schedule_go");
&cmp ($round,192);
&ja (&label("schedule_256"));
&je (&label("schedule_192"));
# 128: fall though
##
## .schedule_128
##
## 128-bit specific part of key schedule.
##
## This schedule is really simple, because all its parts
## are accomplished by the subroutines.
##
&set_label("schedule_128");
&mov ($round,10);
&set_label("loop_schedule_128");
&call ("_vpaes_schedule_round");
&dec ($round);
&jz (&label("schedule_mangle_last"));
&call ("_vpaes_schedule_mangle"); # write output
&jmp (&label("loop_schedule_128"));
##
## .aes_schedule_192
##
## 192-bit specific part of key schedule.
##
## The main body of this schedule is the same as the 128-bit
## schedule, but with more smearing. The long, high side is
## stored in %xmm7 as before, and the short, low side is in
## the high bits of %xmm6.
##
## This schedule is somewhat nastier, however, because each
## round produces 192 bits of key material, or 1.5 round keys.
## Therefore, on each cycle we do 2 rounds and produce 3 round
## keys.
##
&set_label("schedule_192",16);
&movdqu ("xmm0",&QWP(8,$inp)); # load key part 2 (very unaligned)
&call ("_vpaes_schedule_transform"); # input transform
&movdqa ("xmm6","xmm0"); # save short part
&pxor ("xmm4","xmm4"); # clear 4
&movhlps("xmm6","xmm4"); # clobber low side with zeros
&mov ($round,4);
&set_label("loop_schedule_192");
&call ("_vpaes_schedule_round");
&palignr("xmm0","xmm6",8);
&call ("_vpaes_schedule_mangle"); # save key n
&call ("_vpaes_schedule_192_smear");
&call ("_vpaes_schedule_mangle"); # save key n+1
&call ("_vpaes_schedule_round");
&dec ($round);
&jz (&label("schedule_mangle_last"));
&call ("_vpaes_schedule_mangle"); # save key n+2
&call ("_vpaes_schedule_192_smear");
&jmp (&label("loop_schedule_192"));
##
## .aes_schedule_256
##
## 256-bit specific part of key schedule.
##
## The structure here is very similar to the 128-bit
## schedule, but with an additional "low side" in
## %xmm6. The low side's rounds are the same as the
## high side's, except no rcon and no rotation.
##
&set_label("schedule_256",16);
&movdqu ("xmm0",&QWP(16,$inp)); # load key part 2 (unaligned)
&call ("_vpaes_schedule_transform"); # input transform
&mov ($round,7);
&set_label("loop_schedule_256");
&call ("_vpaes_schedule_mangle"); # output low result
&movdqa ("xmm6","xmm0"); # save cur_lo in xmm6
# high round
&call ("_vpaes_schedule_round");
&dec ($round);
&jz (&label("schedule_mangle_last"));
&call ("_vpaes_schedule_mangle");
# low round. swap xmm7 and xmm6
&pshufd ("xmm0","xmm0",0xFF);
&movdqa (&QWP(20,"esp"),"xmm7");
&movdqa ("xmm7","xmm6");
&call ("_vpaes_schedule_low_round");
&movdqa ("xmm7",&QWP(20,"esp"));
&jmp (&label("loop_schedule_256"));
##
## .aes_schedule_mangle_last
##
## Mangler for last round of key schedule
## Mangles %xmm0
## when encrypting, outputs out(%xmm0) ^ 63
## when decrypting, outputs unskew(%xmm0)
##
## Always called right before return... jumps to cleanup and exits
##
&set_label("schedule_mangle_last",16);
# schedule last round key from xmm0
&lea ($base,&DWP($k_deskew,$const));
&test ($out,$out);
&jnz (&label("schedule_mangle_last_dec"));
# encrypting
&movdqa ("xmm1",&QWP($k_sr,$const,$magic));
&pshufb ("xmm0","xmm1"); # output permute
&lea ($base,&DWP($k_opt,$const)); # prepare to output transform
&add ($key,32);
&set_label("schedule_mangle_last_dec");
&add ($key,-16);
&pxor ("xmm0",&QWP($k_s63,$const));
&call ("_vpaes_schedule_transform"); # output transform
&movdqu (&QWP(0,$key),"xmm0"); # save last key
# cleanup
&pxor ("xmm0","xmm0");
&pxor ("xmm1","xmm1");
&pxor ("xmm2","xmm2");
&pxor ("xmm3","xmm3");
&pxor ("xmm4","xmm4");
&pxor ("xmm5","xmm5");
&pxor ("xmm6","xmm6");
&pxor ("xmm7","xmm7");
&ret ();
&function_end_B("_vpaes_schedule_core");
##
## .aes_schedule_192_smear
##
## Smear the short, low side in the 192-bit key schedule.
##
## Inputs:
## %xmm7: high side, b a x y
## %xmm6: low side, d c 0 0
## %xmm13: 0
##
## Outputs:
## %xmm6: b+c+d b+c 0 0
## %xmm0: b+c+d b+c b a
##
&function_begin_B("_vpaes_schedule_192_smear");
&pshufd ("xmm1","xmm6",0x80); # d c 0 0 -> c 0 0 0
&pshufd ("xmm0","xmm7",0xFE); # b a _ _ -> b b b a
&pxor ("xmm6","xmm1"); # -> c+d c 0 0
&pxor ("xmm1","xmm1");
&pxor ("xmm6","xmm0"); # -> b+c+d b+c b a
&movdqa ("xmm0","xmm6");
&movhlps("xmm6","xmm1"); # clobber low side with zeros
&ret ();
&function_end_B("_vpaes_schedule_192_smear");
##
## .aes_schedule_round
##
## Runs one main round of the key schedule on %xmm0, %xmm7
##
## Specifically, runs subbytes on the high dword of %xmm0
## then rotates it by one byte and xors into the low dword of
## %xmm7.
##
## Adds rcon from low byte of %xmm8, then rotates %xmm8 for
## next rcon.
##
## Smears the dwords of %xmm7 by xoring the low into the
## second low, result into third, result into highest.
##
## Returns results in %xmm7 = %xmm0.
## Clobbers %xmm1-%xmm5.
##
&function_begin_B("_vpaes_schedule_round");
# extract rcon from xmm8
&movdqa ("xmm2",&QWP(8,"esp")); # xmm8
&pxor ("xmm1","xmm1");
&palignr("xmm1","xmm2",15);
&palignr("xmm2","xmm2",15);
&pxor ("xmm7","xmm1");
# rotate
&pshufd ("xmm0","xmm0",0xFF);
&palignr("xmm0","xmm0",1);
# fall through...
&movdqa (&QWP(8,"esp"),"xmm2"); # xmm8
# low round: same as high round, but no rotation and no rcon.
&set_label("_vpaes_schedule_low_round");
# smear xmm7
&movdqa ("xmm1","xmm7");
&pslldq ("xmm7",4);
&pxor ("xmm7","xmm1");
&movdqa ("xmm1","xmm7");
&pslldq ("xmm7",8);
&pxor ("xmm7","xmm1");
&pxor ("xmm7",&QWP($k_s63,$const));
# subbyte
&movdqa ("xmm4",&QWP($k_s0F,$const));
&movdqa ("xmm5",&QWP($k_inv,$const)); # 4 : 1/j
&movdqa ("xmm1","xmm4");
&pandn ("xmm1","xmm0");
&psrld ("xmm1",4); # 1 = i
&pand ("xmm0","xmm4"); # 0 = k
&movdqa ("xmm2",&QWP($k_inv+16,$const));# 2 : a/k
&pshufb ("xmm2","xmm0"); # 2 = a/k
&pxor ("xmm0","xmm1"); # 0 = j
&movdqa ("xmm3","xmm5"); # 3 : 1/i
&pshufb ("xmm3","xmm1"); # 3 = 1/i
&pxor ("xmm3","xmm2"); # 3 = iak = 1/i + a/k
&movdqa ("xmm4","xmm5"); # 4 : 1/j
&pshufb ("xmm4","xmm0"); # 4 = 1/j
&pxor ("xmm4","xmm2"); # 4 = jak = 1/j + a/k
&movdqa ("xmm2","xmm5"); # 2 : 1/iak
&pshufb ("xmm2","xmm3"); # 2 = 1/iak
&pxor ("xmm2","xmm0"); # 2 = io
&movdqa ("xmm3","xmm5"); # 3 : 1/jak
&pshufb ("xmm3","xmm4"); # 3 = 1/jak
&pxor ("xmm3","xmm1"); # 3 = jo
&movdqa ("xmm4",&QWP($k_sb1,$const)); # 4 : sbou
&pshufb ("xmm4","xmm2"); # 4 = sbou
&movdqa ("xmm0",&QWP($k_sb1+16,$const));# 0 : sbot
&pshufb ("xmm0","xmm3"); # 0 = sb1t
&pxor ("xmm0","xmm4"); # 0 = sbox output
# add in smeared stuff
&pxor ("xmm0","xmm7");
&movdqa ("xmm7","xmm0");
&ret ();
&function_end_B("_vpaes_schedule_round");
##
## .aes_schedule_transform
##
## Linear-transform %xmm0 according to tables at (%ebx)
##
## Output in %xmm0
## Clobbers %xmm1, %xmm2
##
&function_begin_B("_vpaes_schedule_transform");
&movdqa ("xmm2",&QWP($k_s0F,$const));
&movdqa ("xmm1","xmm2");
&pandn ("xmm1","xmm0");
&psrld ("xmm1",4);
&pand ("xmm0","xmm2");
&movdqa ("xmm2",&QWP(0,$base));
&pshufb ("xmm2","xmm0");
&movdqa ("xmm0",&QWP(16,$base));
&pshufb ("xmm0","xmm1");
&pxor ("xmm0","xmm2");
&ret ();
&function_end_B("_vpaes_schedule_transform");
##
## .aes_schedule_mangle
##
## Mangle xmm0 from (basis-transformed) standard version
## to our version.
##
## On encrypt,
## xor with 0x63
## multiply by circulant 0,1,1,1
## apply shiftrows transform
##
## On decrypt,
## xor with 0x63
## multiply by "inverse mixcolumns" circulant E,B,D,9
## deskew
## apply shiftrows transform
##
##
## Writes out to (%edx), and increments or decrements it
## Keeps track of round number mod 4 in %ecx
## Preserves xmm0
## Clobbers xmm1-xmm5
##
&function_begin_B("_vpaes_schedule_mangle");
&movdqa ("xmm4","xmm0"); # save xmm0 for later
&movdqa ("xmm5",&QWP($k_mc_forward,$const));
&test ($out,$out);
&jnz (&label("schedule_mangle_dec"));
# encrypting
&add ($key,16);
&pxor ("xmm4",&QWP($k_s63,$const));
&pshufb ("xmm4","xmm5");
&movdqa ("xmm3","xmm4");
&pshufb ("xmm4","xmm5");
&pxor ("xmm3","xmm4");
&pshufb ("xmm4","xmm5");
&pxor ("xmm3","xmm4");
&jmp (&label("schedule_mangle_both"));
&set_label("schedule_mangle_dec",16);
# inverse mix columns
&movdqa ("xmm2",&QWP($k_s0F,$const));
&lea ($inp,&DWP($k_dksd,$const));
&movdqa ("xmm1","xmm2");
&pandn ("xmm1","xmm4");
&psrld ("xmm1",4); # 1 = hi
&pand ("xmm4","xmm2"); # 4 = lo
&movdqa ("xmm2",&QWP(0,$inp));
&pshufb ("xmm2","xmm4");
&movdqa ("xmm3",&QWP(0x10,$inp));
&pshufb ("xmm3","xmm1");
&pxor ("xmm3","xmm2");
&pshufb ("xmm3","xmm5");
&movdqa ("xmm2",&QWP(0x20,$inp));
&pshufb ("xmm2","xmm4");
&pxor ("xmm2","xmm3");
&movdqa ("xmm3",&QWP(0x30,$inp));
&pshufb ("xmm3","xmm1");
&pxor ("xmm3","xmm2");
&pshufb ("xmm3","xmm5");
&movdqa ("xmm2",&QWP(0x40,$inp));
&pshufb ("xmm2","xmm4");
&pxor ("xmm2","xmm3");
&movdqa ("xmm3",&QWP(0x50,$inp));
&pshufb ("xmm3","xmm1");
&pxor ("xmm3","xmm2");
&pshufb ("xmm3","xmm5");
&movdqa ("xmm2",&QWP(0x60,$inp));
&pshufb ("xmm2","xmm4");
&pxor ("xmm2","xmm3");
&movdqa ("xmm3",&QWP(0x70,$inp));
&pshufb ("xmm3","xmm1");
&pxor ("xmm3","xmm2");
&add ($key,-16);
&set_label("schedule_mangle_both");
&movdqa ("xmm1",&QWP($k_sr,$const,$magic));
&pshufb ("xmm3","xmm1");
&add ($magic,-16);
&and ($magic,0x30);
&movdqu (&QWP(0,$key),"xmm3");
&ret ();
&function_end_B("_vpaes_schedule_mangle");
#
# Interface to OpenSSL
#
&function_begin("${PREFIX}_set_encrypt_key");
&mov ($inp,&wparam(0)); # inp
&lea ($base,&DWP(-56,"esp"));
&mov ($round,&wparam(1)); # bits
&and ($base,-16);
&mov ($key,&wparam(2)); # key
&xchg ($base,"esp"); # alloca
&mov (&DWP(48,"esp"),$base);
&mov ($base,$round);
&shr ($base,5);
&add ($base,5);
&mov (&DWP(240,$key),$base); # AES_KEY->rounds = nbits/32+5;
&mov ($magic,0x30);
&mov ($out,0);
&lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
&call ("_vpaes_schedule_core");
&set_label("pic_point");
&mov ("esp",&DWP(48,"esp"));
&xor ("eax","eax");
&function_end("${PREFIX}_set_encrypt_key");
&function_begin("${PREFIX}_set_decrypt_key");
&mov ($inp,&wparam(0)); # inp
&lea ($base,&DWP(-56,"esp"));
&mov ($round,&wparam(1)); # bits
&and ($base,-16);
&mov ($key,&wparam(2)); # key
&xchg ($base,"esp"); # alloca
&mov (&DWP(48,"esp"),$base);
&mov ($base,$round);
&shr ($base,5);
&add ($base,5);
&mov (&DWP(240,$key),$base); # AES_KEY->rounds = nbits/32+5;
&shl ($base,4);
&lea ($key,&DWP(16,$key,$base));
&mov ($out,1);
&mov ($magic,$round);
&shr ($magic,1);
&and ($magic,32);
&xor ($magic,32); # nbist==192?0:32;
&lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
&call ("_vpaes_schedule_core");
&set_label("pic_point");
&mov ("esp",&DWP(48,"esp"));
&xor ("eax","eax");
&function_end("${PREFIX}_set_decrypt_key");
&function_begin("${PREFIX}_encrypt");
&lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
&call ("_vpaes_preheat");
&set_label("pic_point");
&mov ($inp,&wparam(0)); # inp
&lea ($base,&DWP(-56,"esp"));
&mov ($out,&wparam(1)); # out
&and ($base,-16);
&mov ($key,&wparam(2)); # key
&xchg ($base,"esp"); # alloca
&mov (&DWP(48,"esp"),$base);
&movdqu ("xmm0",&QWP(0,$inp));
&call ("_vpaes_encrypt_core");
&movdqu (&QWP(0,$out),"xmm0");
&mov ("esp",&DWP(48,"esp"));
&function_end("${PREFIX}_encrypt");
&function_begin("${PREFIX}_decrypt");
&lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
&call ("_vpaes_preheat");
&set_label("pic_point");
&mov ($inp,&wparam(0)); # inp
&lea ($base,&DWP(-56,"esp"));
&mov ($out,&wparam(1)); # out
&and ($base,-16);
&mov ($key,&wparam(2)); # key
&xchg ($base,"esp"); # alloca
&mov (&DWP(48,"esp"),$base);
&movdqu ("xmm0",&QWP(0,$inp));
&call ("_vpaes_decrypt_core");
&movdqu (&QWP(0,$out),"xmm0");
&mov ("esp",&DWP(48,"esp"));
&function_end("${PREFIX}_decrypt");
&function_begin("${PREFIX}_cbc_encrypt");
&mov ($inp,&wparam(0)); # inp
&mov ($out,&wparam(1)); # out
&mov ($round,&wparam(2)); # len
&mov ($key,&wparam(3)); # key
&sub ($round,16);
&jc (&label("cbc_abort"));
&lea ($base,&DWP(-56,"esp"));
&mov ($const,&wparam(4)); # ivp
&and ($base,-16);
&mov ($magic,&wparam(5)); # enc
&xchg ($base,"esp"); # alloca
&movdqu ("xmm1",&QWP(0,$const)); # load IV
&sub ($out,$inp);
&mov (&DWP(48,"esp"),$base);
&mov (&DWP(0,"esp"),$out); # save out
&mov (&DWP(4,"esp"),$key) # save key
&mov (&DWP(8,"esp"),$const); # save ivp
&mov ($out,$round); # $out works as $len
&lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point")));
&call ("_vpaes_preheat");
&set_label("pic_point");
&cmp ($magic,0);
&je (&label("cbc_dec_loop"));
&jmp (&label("cbc_enc_loop"));
&set_label("cbc_enc_loop",16);
&movdqu ("xmm0",&QWP(0,$inp)); # load input
&pxor ("xmm0","xmm1"); # inp^=iv
&call ("_vpaes_encrypt_core");
&mov ($base,&DWP(0,"esp")); # restore out
&mov ($key,&DWP(4,"esp")); # restore key
&movdqa ("xmm1","xmm0");
&movdqu (&QWP(0,$base,$inp),"xmm0"); # write output
&lea ($inp,&DWP(16,$inp));
&sub ($out,16);
&jnc (&label("cbc_enc_loop"));
&jmp (&label("cbc_done"));
&set_label("cbc_dec_loop",16);
&movdqu ("xmm0",&QWP(0,$inp)); # load input
&movdqa (&QWP(16,"esp"),"xmm1"); # save IV
&movdqa (&QWP(32,"esp"),"xmm0"); # save future IV
&call ("_vpaes_decrypt_core");
&mov ($base,&DWP(0,"esp")); # restore out
&mov ($key,&DWP(4,"esp")); # restore key
&pxor ("xmm0",&QWP(16,"esp")); # out^=iv
&movdqa ("xmm1",&QWP(32,"esp")); # load next IV
&movdqu (&QWP(0,$base,$inp),"xmm0"); # write output
&lea ($inp,&DWP(16,$inp));
&sub ($out,16);
&jnc (&label("cbc_dec_loop"));
&set_label("cbc_done");
&mov ($base,&DWP(8,"esp")); # restore ivp
&mov ("esp",&DWP(48,"esp"));
&movdqu (&QWP(0,$base),"xmm1"); # write IV
&set_label("cbc_abort");
&function_end("${PREFIX}_cbc_encrypt");
&asm_finish();

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,5 @@
/* crypto/aes/aes_misc.c -*- mode:C; c-file-style: "eay" -*- */
/* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
* Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -45,41 +44,44 @@
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
*/
* ==================================================================== */
//#include <openssl/opensslv.h>
//#include <openssl/crypto.h>
#include "aes.h"
#include "aes_locl.h"
#ifndef OPENSSL_HEADER_AES_INTERNAL_H
#define OPENSSL_HEADER_AES_INTERNAL_H
const char AES_version[]="AES" ;//OPENSSL_VERSION_PTEXT;
#include <openssl/base.h>
const char *AES_options(void) {
#ifdef FULL_UNROLL
return "aes(full)";
#else
return "aes(partial)";
#if defined(__cplusplus)
extern "C" {
#endif
}
/* FIPS wrapper functions to block low level AES calls in FIPS mode */
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key)
{
#ifdef OPENSSL_FIPS
fips_cipher_abort(AES);
#if defined(_MSC_VER) && \
(defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
#define GETU32(p) SWAP(*((uint32_t *)(p)))
#define PUTU32(ct, st) \
{ *((uint32_t *)(ct)) = SWAP((st)); }
#else
#define GETU32(pt) \
(((uint32_t)(pt)[0] << 24) ^ ((uint32_t)(pt)[1] << 16) ^ \
((uint32_t)(pt)[2] << 8) ^ ((uint32_t)(pt)[3]))
#define PUTU32(ct, st) \
{ \
(ct)[0] = (uint8_t)((st) >> 24); \
(ct)[1] = (uint8_t)((st) >> 16); \
(ct)[2] = (uint8_t)((st) >> 8); \
(ct)[3] = (uint8_t)(st); \
}
#endif
return private_AES_set_encrypt_key(userKey, bits, key);
}
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key)
{
#ifdef OPENSSL_FIPS
fips_cipher_abort(AES);
#define MAXKC (256 / 32)
#define MAXKB (256 / 8)
#define MAXNR 14
#if defined(__cplusplus)
} /* extern C */
#endif
return private_AES_set_decrypt_key(userKey, bits, key);
}
#endif /* OPENSSL_HEADER_AES_INTERNAL_H */

View File

@ -0,0 +1,108 @@
/* ====================================================================
* Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ==================================================================== */
#include <openssl/aes.h>
#include "assert.h"
#include <openssl/modes.h>
void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t ivec[AES_BLOCK_SIZE],
uint8_t ecount_buf[AES_BLOCK_SIZE], unsigned int *num) {
CRYPTO_ctr128_encrypt(in, out, len, key, ivec, ecount_buf, num,
(block128_f)AES_encrypt);
}
void AES_ecb_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key,
const int enc) {
assert(in && out && key);
assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
if (AES_ENCRYPT == enc) {
AES_encrypt(in, out, key);
} else {
AES_decrypt(in, out, key);
}
}
#if defined(OPENSSL_NO_ASM) || \
(!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86))
void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t *ivec, const int enc) {
if (enc) {
CRYPTO_cbc128_encrypt(in, out, len, key, ivec, (block128_f)AES_encrypt);
} else {
CRYPTO_cbc128_decrypt(in, out, len, key, ivec, (block128_f)AES_decrypt);
}
}
#else
void asm_AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t *ivec, const int enc);
void AES_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t *ivec, const int enc) {
asm_AES_cbc_encrypt(in, out, len, key, ivec, enc);
}
#endif /* OPENSSL_NO_ASM || (!OPENSSL_X86_64 && !OPENSSL_X86) */
void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
const AES_KEY *key, uint8_t *ivec, int *num) {
CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
(block128_f)AES_encrypt);
}
void AES_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
const AES_KEY *key, uint8_t *ivec, int *num,
int enc) {
CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
(block128_f)AES_encrypt);
}

View File

@ -0,0 +1,136 @@
/* ====================================================================
* Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#ifndef OPENSSL_HEADER_ARM_ARCH_H
#define OPENSSL_HEADER_ARM_ARCH_H
#if !defined(__ARM_ARCH__)
# if defined(__CC_ARM)
# define __ARM_ARCH__ __TARGET_ARCH_ARM
# if defined(__BIG_ENDIAN)
# define __ARMEB__
# else
# define __ARMEL__
# endif
# elif defined(__GNUC__)
# if defined(__aarch64__)
# define __ARM_ARCH__ 8
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define __ARMEB__
# else
# define __ARMEL__
# endif
/* Why doesn't gcc define __ARM_ARCH__? Instead it defines
* bunch of below macros. See all_architectires[] table in
* gcc/config/arm/arm.c. On a side note it defines
* __ARMEL__/__ARMEB__ for little-/big-endian. */
# elif defined(__ARM_ARCH)
# define __ARM_ARCH__ __ARM_ARCH
# elif defined(__ARM_ARCH_8A__)
# define __ARM_ARCH__ 8
# elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__) || \
defined(__ARM_ARCH_7EM__)
# define __ARM_ARCH__ 7
# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
defined(__ARM_ARCH_6K__)|| defined(__ARM_ARCH_6M__) || \
defined(__ARM_ARCH_6Z__)|| defined(__ARM_ARCH_6ZK__) || \
defined(__ARM_ARCH_6T2__)
# define __ARM_ARCH__ 6
# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \
defined(__ARM_ARCH_5E__)|| defined(__ARM_ARCH_5TE__) || \
defined(__ARM_ARCH_5TEJ__)
# define __ARM_ARCH__ 5
# elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
# define __ARM_ARCH__ 4
# else
# error "unsupported ARM architecture"
# endif
# endif
#endif
/* Even when building for 32-bit ARM, support for aarch64 crypto instructions
* will be included. */
#define __ARM_MAX_ARCH__ 8
#if !__ASSEMBLER__
/* OPENSSL_armcap_P contains flags describing the capabilities of the CPU and
* is easy for assembly code to acesss. For C code, see the functions in
* |cpu.h|. */
extern uint32_t OPENSSL_armcap_P;
#endif /* !__ASSEMBLER__ */
/* ARMV7_NEON is true when a NEON unit is present in the current CPU. */
#define ARMV7_NEON (1 << 0)
/* ARMV7_NEON_FUNCTIONAL is true when the NEON unit doesn't contain subtle bugs.
* The Poly1305 NEON code is known to trigger bugs in the NEON units of some
* phones. If this bit isn't set then the Poly1305 NEON code won't be used.
* See https://code.google.com/p/chromium/issues/detail?id=341598. */
#define ARMV7_NEON_FUNCTIONAL (1 << 10)
/* ARMV8_AES indicates support for hardware AES instructions. */
#define ARMV8_AES (1 << 2)
/* ARMV8_SHA1 indicates support for hardware SHA-1 instructions. */
#define ARMV8_SHA1 (1 << 3)
/* ARMV8_SHA256 indicates support for hardware SHA-256 instructions. */
#define ARMV8_SHA256 (1 << 4)
/* ARMV8_PMULL indicates support for carryless multiplication. */
#define ARMV8_PMULL (1 << 5)
#endif /* OPENSSL_HEADER_THREAD_H */

View File

@ -0,0 +1,45 @@
include_directories(. .. ../../include)
add_library(
asn1
OBJECT
a_bitstr.c
a_bool.c
a_bytes.c
a_d2i_fp.c
a_dup.c
a_enum.c
a_gentm.c
a_i2d_fp.c
a_int.c
a_mbstr.c
a_object.c
a_octet.c
a_print.c
a_strnid.c
a_time.c
a_type.c
a_utctm.c
a_utf8.c
asn1_lib.c
asn1_par.c
asn_pack.c
bio_asn1.c
bio_ndef.c
f_enum.c
f_int.c
f_string.c
t_bitst.c
t_pkey.c
tasn_dec.c
tasn_enc.c
tasn_fre.c
tasn_new.c
tasn_prn.c
tasn_typ.c
tasn_utl.c
x_bignum.c
x_long.c
)

View File

@ -0,0 +1,255 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
{ return M_ASN1_BIT_STRING_set(x, d, len); }
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
{
int ret,j,bits,len;
unsigned char *p,*d;
if (a == NULL) return(0);
len=a->length;
if (len > 0)
{
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT)
{
bits=(int)a->flags&0x07;
}
else
{
for ( ; len > 0; len--)
{
if (a->data[len-1]) break;
}
j=a->data[len-1];
if (j & 0x01) bits=0;
else if (j & 0x02) bits=1;
else if (j & 0x04) bits=2;
else if (j & 0x08) bits=3;
else if (j & 0x10) bits=4;
else if (j & 0x20) bits=5;
else if (j & 0x40) bits=6;
else if (j & 0x80) bits=7;
else bits=0; /* should not happen */
}
}
else
bits=0;
ret=1+len;
if (pp == NULL) return(ret);
p= *pp;
*(p++)=(unsigned char)bits;
d=a->data;
memcpy(p,d,len);
p+=len;
if (len > 0) p[-1]&=(0xff<<bits);
*pp=p;
return(ret);
}
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
const unsigned char **pp, long len)
{
ASN1_BIT_STRING *ret=NULL;
const unsigned char *p;
unsigned char *s;
int padding;
if (len < 1)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
goto err;
}
if ((a == NULL) || ((*a) == NULL))
{
if ((ret=M_ASN1_BIT_STRING_new()) == NULL) return(NULL);
}
else
ret=(*a);
p= *pp;
padding = *(p++);
if (padding > 7)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
goto err;
}
/* We do this to preserve the settings. If we modify
* the settings, via the _set_bit function, we will recalculate
* on output */
ret->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
ret->flags|=(ASN1_STRING_FLAG_BITS_LEFT|padding); /* set */
if (len-- > 1) /* using one because of the bits left byte */
{
s=(unsigned char *)OPENSSL_malloc((int)len);
if (s == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
memcpy(s,p,(int)len);
s[len-1]&=(0xff<<padding);
p+=len;
}
else
s=NULL;
ret->length=(int)len;
if (ret->data != NULL) OPENSSL_free(ret->data);
ret->data=s;
ret->type=V_ASN1_BIT_STRING;
if (a != NULL) (*a)=ret;
*pp=p;
return(ret);
err:
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_BIT_STRING_free(ret);
return(NULL);
}
/* These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
*/
int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
{
int w,v,iv;
unsigned char *c;
w=n/8;
v=1<<(7-(n&0x07));
iv= ~v;
if (!value) v=0;
if (a == NULL)
return 0;
a->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear, set on write */
if ((a->length < (w+1)) || (a->data == NULL))
{
if (!value) return(1); /* Don't need to set */
if (a->data == NULL)
c=(unsigned char *)OPENSSL_malloc(w+1);
else
c=(unsigned char *)OPENSSL_realloc_clean(a->data,
a->length,
w+1);
if (c == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
if (w+1-a->length > 0) memset(c+a->length, 0, w+1-a->length);
a->data=c;
a->length=w+1;
}
a->data[w]=((a->data[w])&iv)|v;
while ((a->length > 0) && (a->data[a->length-1] == 0))
a->length--;
return(1);
}
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
{
int w,v;
w=n/8;
v=1<<(7-(n&0x07));
if ((a == NULL) || (a->length < (w+1)) || (a->data == NULL))
return(0);
return((a->data[w]&v) != 0);
}
/*
* Checks if the given bit string contains only bits specified by
* the flags vector. Returns 0 if there is at least one bit set in 'a'
* which is not specified in 'flags', 1 otherwise.
* 'len' is the length of 'flags'.
*/
int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a,
unsigned char *flags, int flags_len)
{
int i, ok;
/* Check if there is one bit set at all. */
if (!a || !a->data) return 1;
/* Check each byte of the internal representation of the bit string. */
ok = 1;
for (i = 0; i < a->length && ok; ++i)
{
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
/* We are done if there is an unneeded bit set. */
ok = (a->data[i] & mask) == 0;
}
return ok;
}

View File

@ -0,0 +1,112 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
{
int r;
unsigned char *p;
r=ASN1_object_size(0,1,V_ASN1_BOOLEAN);
if (pp == NULL) return(r);
p= *pp;
ASN1_put_object(&p,0,1,V_ASN1_BOOLEAN,V_ASN1_UNIVERSAL);
*(p++)= (unsigned char)a;
*pp=p;
return(r);
}
int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
{
int ret= -1;
const unsigned char *p;
long len;
int inf,tag,xclass;
int i=0;
p= *pp;
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
if (inf & 0x80)
{
i=ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != V_ASN1_BOOLEAN)
{
i=ASN1_R_EXPECTING_A_BOOLEAN;
goto err;
}
if (len != 1)
{
i=ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
goto err;
}
ret= (int)*(p++);
if (a != NULL) (*a)=ret;
*pp=p;
return(ret);
err:
OPENSSL_PUT_ERROR(ASN1, i);
return(ret);
}

View File

@ -0,0 +1,317 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c);
/* type is a 'bitmap' of acceptable string types.
*/
ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp,
long length, int type)
{
ASN1_STRING *ret=NULL;
const unsigned char *p;
unsigned char *s;
long len;
int inf,tag,xclass;
int i=0;
p= *pp;
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
if (inf & 0x80) goto err;
if (tag >= 32)
{
i=ASN1_R_TAG_VALUE_TOO_HIGH;
goto err;
}
if (!(ASN1_tag2bit(tag) & type))
{
i=ASN1_R_WRONG_TYPE;
goto err;
}
/* If a bit-string, exit early */
if (tag == V_ASN1_BIT_STRING)
return(d2i_ASN1_BIT_STRING(a,pp,length));
if ((a == NULL) || ((*a) == NULL))
{
if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
}
else
ret=(*a);
if (len != 0)
{
s=(unsigned char *)OPENSSL_malloc((int)len+1);
if (s == NULL)
{
i=ERR_R_MALLOC_FAILURE;
goto err;
}
memcpy(s,p,(int)len);
s[len]='\0';
p+=len;
}
else
s=NULL;
if (ret->data != NULL) OPENSSL_free(ret->data);
ret->length=(int)len;
ret->data=s;
ret->type=tag;
if (a != NULL) (*a)=ret;
*pp=p;
return(ret);
err:
OPENSSL_PUT_ERROR(ASN1, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
ASN1_STRING_free(ret);
return(NULL);
}
int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
{
int ret,r,constructed;
unsigned char *p;
if (a == NULL) return(0);
if (tag == V_ASN1_BIT_STRING)
return(i2d_ASN1_BIT_STRING(a,pp));
ret=a->length;
r=ASN1_object_size(0,ret,tag);
if (pp == NULL) return(r);
p= *pp;
if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET))
constructed=1;
else
constructed=0;
ASN1_put_object(&p,constructed,ret,tag,xclass);
memcpy(p,a->data,a->length);
p+=a->length;
*pp= p;
return(r);
}
ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
long length, int Ptag, int Pclass)
{
ASN1_STRING *ret=NULL;
const unsigned char *p;
unsigned char *s;
long len;
int inf,tag,xclass;
int i=0;
if ((a == NULL) || ((*a) == NULL))
{
if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
}
else
ret=(*a);
p= *pp;
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
if (inf & 0x80)
{
i=ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != Ptag)
{
i=ASN1_R_WRONG_TAG;
goto err;
}
if (inf & V_ASN1_CONSTRUCTED)
{
ASN1_const_CTX c;
c.pp=pp;
c.p=p;
c.inf=inf;
c.slen=len;
c.tag=Ptag;
c.xclass=Pclass;
c.max=(length == 0)?0:(p+length);
if (!asn1_collate_primitive(ret,&c))
goto err;
else
{
p=c.p;
}
}
else
{
if (len != 0)
{
if ((ret->length < len) || (ret->data == NULL))
{
if (ret->data != NULL) OPENSSL_free(ret->data);
s=(unsigned char *)OPENSSL_malloc((int)len + 1);
if (s == NULL)
{
i=ERR_R_MALLOC_FAILURE;
goto err;
}
}
else
s=ret->data;
memcpy(s,p,(int)len);
s[len] = '\0';
p+=len;
}
else
{
s=NULL;
if (ret->data != NULL) OPENSSL_free(ret->data);
}
ret->length=(int)len;
ret->data=s;
ret->type=Ptag;
}
if (a != NULL) (*a)=ret;
*pp=p;
return(ret);
err:
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
ASN1_STRING_free(ret);
OPENSSL_PUT_ERROR(ASN1, i);
return(NULL);
}
/* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse
* them into the one structure that is then returned */
/* There have been a few bug fixes for this function from
* Paul Keogh <paul.keogh@sse.ie>, many thanks to him */
static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
{
ASN1_STRING *os=NULL;
BUF_MEM b;
int num;
b.length=0;
b.max=0;
b.data=NULL;
if (a == NULL)
{
c->error=ERR_R_PASSED_NULL_PARAMETER;
goto err;
}
num=0;
for (;;)
{
if (c->inf & 1)
{
c->eos=ASN1_const_check_infinite_end(&c->p,
(long)(c->max-c->p));
if (c->eos) break;
}
else
{
if (c->slen <= 0) break;
}
c->q=c->p;
if (d2i_ASN1_bytes(&os,&c->p,c->max-c->p,c->tag,c->xclass)
== NULL)
{
c->error=ERR_R_ASN1_LIB;
goto err;
}
if (!BUF_MEM_grow_clean(&b,num+os->length))
{
c->error=ERR_R_BUF_LIB;
goto err;
}
memcpy(&(b.data[num]),os->data,os->length);
if (!(c->inf & 1))
c->slen-=(c->p-c->q);
num+=os->length;
}
if (!asn1_const_Finish(c)) goto err;
a->length=num;
if (a->data != NULL) OPENSSL_free(a->data);
a->data=(unsigned char *)b.data;
if (os != NULL) ASN1_STRING_free(os);
return(1);
err:
OPENSSL_PUT_ERROR(ASN1, c->error);
if (os != NULL) ASN1_STRING_free(os);
if (b.data != NULL) OPENSSL_free(b.data);
return(0);
}

View File

@ -0,0 +1,286 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <limits.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
#ifndef NO_OLD_ASN1
#ifndef OPENSSL_NO_FP_API
void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x)
{
BIO *b;
void *ret;
if ((b=BIO_new(BIO_s_file())) == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
return(NULL);
}
BIO_set_fp(b,in,BIO_NOCLOSE);
ret=ASN1_d2i_bio(xnew,d2i,b,x);
BIO_free(b);
return(ret);
}
#endif
void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x)
{
BUF_MEM *b = NULL;
const unsigned char *p;
void *ret=NULL;
int len;
len = asn1_d2i_read_bio(in, &b);
if(len < 0) goto err;
p=(unsigned char *)b->data;
ret=d2i(x,&p,len);
err:
if (b != NULL) BUF_MEM_free(b);
return(ret);
}
#endif
void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
{
BUF_MEM *b = NULL;
const unsigned char *p;
void *ret=NULL;
int len;
len = asn1_d2i_read_bio(in, &b);
if(len < 0) goto err;
p=(const unsigned char *)b->data;
ret=ASN1_item_d2i(x,&p,len, it);
err:
if (b != NULL) BUF_MEM_free(b);
return(ret);
}
#ifndef OPENSSL_NO_FP_API
void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
{
BIO *b;
char *ret;
if ((b=BIO_new(BIO_s_file())) == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
return(NULL);
}
BIO_set_fp(b,in,BIO_NOCLOSE);
ret=ASN1_item_d2i_bio(it,b,x);
BIO_free(b);
return(ret);
}
#endif
#define HEADER_SIZE 8
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
BUF_MEM *b;
unsigned char *p;
int i;
ASN1_const_CTX c;
size_t want=HEADER_SIZE;
int eos=0;
size_t off=0;
size_t len=0;
b=BUF_MEM_new();
if (b == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
ERR_clear_error();
for (;;)
{
if (want >= (len-off))
{
want-=(len-off);
if (len + want < len || !BUF_MEM_grow_clean(b,len+want))
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
i=BIO_read(in,&(b->data[len]),want);
if ((i < 0) && ((len-off) == 0))
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
if (i > 0)
{
if (len+i < len)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
goto err;
}
len+=i;
}
}
/* else data already loaded */
p=(unsigned char *)&(b->data[off]);
c.p=p;
c.inf=ASN1_get_object(&(c.p),&(c.slen),&(c.tag),&(c.xclass),
len-off);
if (c.inf & 0x80)
{
uint32_t e;
e=ERR_GET_REASON(ERR_peek_error());
if (e != ASN1_R_TOO_LONG)
goto err;
else
ERR_clear_error(); /* clear error */
}
i=c.p-p;/* header length */
off+=i; /* end of data */
if (c.inf & 1)
{
/* no data body so go round again */
eos++;
if (eos < 0)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
goto err;
}
want=HEADER_SIZE;
}
else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC))
{
/* eos value, so go back and read another header */
eos--;
if (eos <= 0)
break;
else
want=HEADER_SIZE;
}
else
{
/* suck in c.slen bytes of data */
want=c.slen;
if (want > (len-off))
{
want-=(len-off);
if (want > INT_MAX /* BIO_read takes an int length */ ||
len+want < len)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
goto err;
}
if (!BUF_MEM_grow_clean(b,len+want))
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
while (want > 0)
{
i=BIO_read(in,&(b->data[len]),want);
if (i <= 0)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
/* This can't overflow because
* |len+want| didn't overflow. */
len+=i;
want-=i;
}
}
if (off + c.slen < off)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
goto err;
}
off+=c.slen;
if (eos <= 0)
{
break;
}
else
want=HEADER_SIZE;
}
}
if (off > INT_MAX)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
goto err;
}
*pb = b;
return off;
err:
if (b != NULL) BUF_MEM_free(b);
return -1;
}

View File

@ -0,0 +1,103 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
{
unsigned char *b,*p;
const unsigned char *p2;
int i;
char *ret;
if (x == NULL) return(NULL);
i=i2d(x,NULL);
b=OPENSSL_malloc(i+10);
if (b == NULL)
{ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); return(NULL); }
p= b;
i=i2d(x,&p);
p2= b;
ret=d2i(NULL,&p2,i);
OPENSSL_free(b);
return(ret);
}
/* ASN1_ITEM version of dup: this follows the model above except we don't need
* to allocate the buffer. At some point this could be rewritten to directly dup
* the underlying structure instead of doing and encode and decode. */
void *ASN1_item_dup(const ASN1_ITEM *it, void *x)
{
unsigned char *b = NULL;
const unsigned char *p;
long i;
void *ret;
if (x == NULL) return(NULL);
i=ASN1_item_i2d(x,&b,it);
if (b == NULL)
{ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); return(NULL); }
p= b;
ret=ASN1_item_d2i(NULL,&p,i, it);
OPENSSL_free(b);
return(ret);
}

View File

@ -0,0 +1,183 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
/*
* Code for ENUMERATED type: identical to INTEGER apart from a different tag.
* for comments on encoding see a_int.c
*/
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
{
int j,k;
unsigned int i;
unsigned char buf[sizeof(long)+1];
long d;
a->type=V_ASN1_ENUMERATED;
if (a->length < (int)(sizeof(long)+1))
{
if (a->data != NULL)
OPENSSL_free(a->data);
if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL)
memset((char *)a->data,0,sizeof(long)+1);
}
if (a->data == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return(0);
}
d=v;
if (d < 0)
{
d= -d;
a->type=V_ASN1_NEG_ENUMERATED;
}
for (i=0; i<sizeof(long); i++)
{
if (d == 0) break;
buf[i]=(int)d&0xff;
d>>=8;
}
j=0;
for (k=i-1; k >=0; k--)
a->data[j++]=buf[k];
a->length=j;
return(1);
}
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
{
int neg=0,i;
long r=0;
if (a == NULL) return(0L);
i=a->type;
if (i == V_ASN1_NEG_ENUMERATED)
neg=1;
else if (i != V_ASN1_ENUMERATED)
return -1;
if (a->length > (int)sizeof(long))
{
/* hmm... a bit ugly */
return(0xffffffffL);
}
if (a->data == NULL)
return 0;
for (i=0; i<a->length; i++)
{
r<<=8;
r|=(unsigned char)a->data[i];
}
if (neg) r= -r;
return(r);
}
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
{
ASN1_ENUMERATED *ret;
int len,j;
if (ai == NULL)
ret=M_ASN1_ENUMERATED_new();
else
ret=ai;
if (ret == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
goto err;
}
if(BN_is_negative(bn)) ret->type = V_ASN1_NEG_ENUMERATED;
else ret->type=V_ASN1_ENUMERATED;
j=BN_num_bits(bn);
len=((j == 0)?0:((j/8)+1));
if (ret->length < len+4)
{
unsigned char *new_data=OPENSSL_realloc(ret->data, len+4);
if (!new_data)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->data=new_data;
}
ret->length=BN_bn2bin(bn,ret->data);
return(ret);
err:
if (ret != ai) M_ASN1_ENUMERATED_free(ret);
return(NULL);
}
BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn)
{
BIGNUM *ret;
if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
else if(ai->type == V_ASN1_NEG_ENUMERATED) BN_set_negative(ret,1);
return(ret);
}

View File

@ -0,0 +1,255 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <time.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/time_support.h>
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
{
static const int min[9]={ 0, 0, 1, 1, 0, 0, 0, 0, 0};
static const int max[9]={99, 99,12,31,23,59,59,12,59};
char *a;
int n,i,l,o;
if (d->type != V_ASN1_GENERALIZEDTIME) return(0);
l=d->length;
a=(char *)d->data;
o=0;
/* GENERALIZEDTIME is similar to UTCTIME except the year is
* represented as YYYY. This stuff treats everything as a two digit
* field so make first two fields 00 to 99
*/
if (l < 13) goto err;
for (i=0; i<7; i++)
{
if ((i == 6) && ((a[o] == 'Z') ||
(a[o] == '+') || (a[o] == '-')))
{
i++;
if (tm)
tm->tm_sec = 0;
break;
}
if ((a[o] < '0') || (a[o] > '9')) goto err;
n= a[o]-'0';
if (++o > l) goto err;
if ((a[o] < '0') || (a[o] > '9')) goto err;
n=(n*10)+ a[o]-'0';
if (++o > l) goto err;
if ((n < min[i]) || (n > max[i])) goto err;
if (tm)
{
switch(i)
{
case 0:
tm->tm_year = n * 100 - 1900;
break;
case 1:
tm->tm_year += n;
break;
case 2:
tm->tm_mon = n - 1;
break;
case 3:
tm->tm_mday = n;
break;
case 4:
tm->tm_hour = n;
break;
case 5:
tm->tm_min = n;
break;
case 6:
tm->tm_sec = n;
break;
}
}
}
/* Optional fractional seconds: decimal point followed by one
* or more digits.
*/
if (a[o] == '.')
{
if (++o > l) goto err;
i = o;
while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
o++;
/* Must have at least one digit after decimal point */
if (i == o) goto err;
}
if (a[o] == 'Z')
o++;
else if ((a[o] == '+') || (a[o] == '-'))
{
int offsign = a[o] == '-' ? -1 : 1, offset = 0;
o++;
if (o+4 > l) goto err;
for (i=7; i<9; i++)
{
if ((a[o] < '0') || (a[o] > '9')) goto err;
n= a[o]-'0';
o++;
if ((a[o] < '0') || (a[o] > '9')) goto err;
n=(n*10)+ a[o]-'0';
if ((n < min[i]) || (n > max[i])) goto err;
if (tm)
{
if (i == 7)
offset = n * 3600;
else if (i == 8)
offset += n * 60;
}
o++;
}
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
return 0;
}
else if (a[o])
{
/* Missing time zone information. */
goto err;
}
return(o == l);
err:
return(0);
}
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
{
return asn1_generalizedtime_to_tm(NULL, d);
}
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
{
ASN1_GENERALIZEDTIME t;
t.type=V_ASN1_GENERALIZEDTIME;
t.length=strlen(str);
t.data=(unsigned char *)str;
if (ASN1_GENERALIZEDTIME_check(&t))
{
if (s != NULL)
{
if (!ASN1_STRING_set((ASN1_STRING *)s,
(unsigned char *)str,t.length))
return 0;
s->type=V_ASN1_GENERALIZEDTIME;
}
return(1);
}
else
return(0);
}
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
time_t t)
{
return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
}
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
time_t t, int offset_day, long offset_sec)
{
char *p;
struct tm *ts;
struct tm data;
size_t len = 20;
if (s == NULL)
s=M_ASN1_GENERALIZEDTIME_new();
if (s == NULL)
return(NULL);
ts=OPENSSL_gmtime(&t, &data);
if (ts == NULL)
return(NULL);
if (offset_day || offset_sec)
{
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
return NULL;
}
p=(char *)s->data;
if ((p == NULL) || ((size_t)s->length < len))
{
p=OPENSSL_malloc(len);
if (p == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return(NULL);
}
if (s->data != NULL)
OPENSSL_free(s->data);
s->data=(unsigned char *)p;
}
BIO_snprintf(p,len,"%04d%02d%02d%02d%02d%02dZ",ts->tm_year + 1900,
ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
s->length=strlen(p);
s->type=V_ASN1_GENERALIZEDTIME;
return(s);
}

View File

@ -0,0 +1,154 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
{
BIO *b;
int ret;
if ((b=BIO_new(BIO_s_file())) == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
return(0);
}
BIO_set_fp(b,out,BIO_NOCLOSE);
ret=ASN1_i2d_bio(i2d,b,x);
BIO_free(b);
return(ret);
}
int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x)
{
char *b;
unsigned char *p;
int i,j=0,n,ret=1;
n=i2d(x,NULL);
b=(char *)OPENSSL_malloc(n);
if (b == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return(0);
}
p=(unsigned char *)b;
i2d(x,&p);
for (;;)
{
i=BIO_write(out,&(b[j]),n);
if (i == n) break;
if (i <= 0)
{
ret=0;
break;
}
j+=i;
n-=i;
}
OPENSSL_free(b);
return(ret);
}
int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
{
BIO *b;
int ret;
if ((b=BIO_new(BIO_s_file())) == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
return(0);
}
BIO_set_fp(b,out,BIO_NOCLOSE);
ret=ASN1_item_i2d_bio(it,b,x);
BIO_free(b);
return(ret);
}
int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
{
unsigned char *b = NULL;
int i,j=0,n,ret=1;
n = ASN1_item_i2d(x, &b, it);
if (b == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return(0);
}
for (;;)
{
i=BIO_write(out,&(b[j]),n);
if (i == n) break;
if (i <= 0)
{
ret=0;
break;
}
j+=i;
n-=i;
}
OPENSSL_free(b);
return(ret);
}

View File

@ -0,0 +1,456 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
{ return M_ASN1_INTEGER_dup(x);}
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
{
int neg, ret;
/* Compare signs */
neg = x->type & V_ASN1_NEG;
if (neg != (y->type & V_ASN1_NEG))
{
if (neg)
return -1;
else
return 1;
}
ret = ASN1_STRING_cmp(x, y);
if (neg)
return -ret;
else
return ret;
}
/*
* This converts an ASN1 INTEGER into its content encoding.
* The internal representation is an ASN1_STRING whose data is a big endian
* representation of the value, ignoring the sign. The sign is determined by
* the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
*
* Positive integers are no problem: they are almost the same as the DER
* encoding, except if the first byte is >= 0x80 we need to add a zero pad.
*
* Negative integers are a bit trickier...
* The DER representation of negative integers is in 2s complement form.
* The internal form is converted by complementing each octet and finally
* adding one to the result. This can be done less messily with a little trick.
* If the internal form has trailing zeroes then they will become FF by the
* complement and 0 by the add one (due to carry) so just copy as many trailing
* zeros to the destination as there are in the source. The carry will add one
* to the last none zero octet: so complement this octet and add one and finally
* complement any left over until you get to the start of the string.
*
* Padding is a little trickier too. If the first bytes is > 0x80 then we pad
* with 0xff. However if the first byte is 0x80 and one of the following bytes
* is non-zero we pad with 0xff. The reason for this distinction is that 0x80
* followed by optional zeros isn't padded.
*/
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
{
int pad=0,ret,i,neg;
unsigned char *p,*n,pb=0;
if (a == NULL) return(0);
neg=a->type & V_ASN1_NEG;
if (a->length == 0)
ret=1;
else
{
ret=a->length;
i=a->data[0];
if (!neg && (i > 127)) {
pad=1;
pb=0;
} else if(neg) {
if(i>128) {
pad=1;
pb=0xFF;
} else if(i == 128) {
/*
* Special case: if any other bytes non zero we pad:
* otherwise we don't.
*/
for(i = 1; i < a->length; i++) if(a->data[i]) {
pad=1;
pb=0xFF;
break;
}
}
}
ret+=pad;
}
if (pp == NULL) return(ret);
p= *pp;
if (pad) *(p++)=pb;
if (a->length == 0) *(p++)=0;
else if (!neg) memcpy(p,a->data,(unsigned int)a->length);
else {
/* Begin at the end of the encoding */
n=a->data + a->length - 1;
p += a->length - 1;
i = a->length;
/* Copy zeros to destination as long as source is zero */
while(!*n) {
*(p--) = 0;
n--;
i--;
}
/* Complement and increment next octet */
*(p--) = ((*(n--)) ^ 0xff) + 1;
i--;
/* Complement any octets left */
for(;i > 0; i--) *(p--) = *(n--) ^ 0xff;
}
*pp+=ret;
return(ret);
}
/* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
long len)
{
ASN1_INTEGER *ret=NULL;
const unsigned char *p, *pend;
unsigned char *to,*s;
int i;
if ((a == NULL) || ((*a) == NULL))
{
if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
ret->type=V_ASN1_INTEGER;
}
else
ret=(*a);
p= *pp;
pend = p + len;
/* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
* signifies a missing NULL parameter. */
s=(unsigned char *)OPENSSL_malloc((int)len+1);
if (s == NULL)
{
i=ERR_R_MALLOC_FAILURE;
goto err;
}
to=s;
if(!len) {
/* Strictly speaking this is an illegal INTEGER but we
* tolerate it.
*/
ret->type=V_ASN1_INTEGER;
} else if (*p & 0x80) /* a negative number */
{
ret->type=V_ASN1_NEG_INTEGER;
if ((*p == 0xff) && (len != 1)) {
p++;
len--;
}
i = len;
p += i - 1;
to += i - 1;
while((!*p) && i) {
*(to--) = 0;
i--;
p--;
}
/* Special case: if all zeros then the number will be of
* the form FF followed by n zero bytes: this corresponds to
* 1 followed by n zero bytes. We've already written n zeros
* so we just append an extra one and set the first byte to
* a 1. This is treated separately because it is the only case
* where the number of bytes is larger than len.
*/
if(!i) {
*s = 1;
s[len] = 0;
len++;
} else {
*(to--) = (*(p--) ^ 0xff) + 1;
i--;
for(;i > 0; i--) *(to--) = *(p--) ^ 0xff;
}
} else {
ret->type=V_ASN1_INTEGER;
if ((*p == 0) && (len != 1))
{
p++;
len--;
}
memcpy(s,p,(int)len);
}
if (ret->data != NULL) OPENSSL_free(ret->data);
ret->data=s;
ret->length=(int)len;
if (a != NULL) (*a)=ret;
*pp=pend;
return(ret);
err:
OPENSSL_PUT_ERROR(ASN1, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_INTEGER_free(ret);
return(NULL);
}
/* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of
* ASN1 integers: some broken software can encode a positive INTEGER
* with its MSB set as negative (it doesn't add a padding zero).
*/
ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
long length)
{
ASN1_INTEGER *ret=NULL;
const unsigned char *p;
unsigned char *s;
long len;
int inf,tag,xclass;
int i;
if ((a == NULL) || ((*a) == NULL))
{
if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
ret->type=V_ASN1_INTEGER;
}
else
ret=(*a);
p= *pp;
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
if (inf & 0x80)
{
i=ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != V_ASN1_INTEGER)
{
i=ASN1_R_EXPECTING_AN_INTEGER;
goto err;
}
/* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
* signifies a missing NULL parameter. */
s=(unsigned char *)OPENSSL_malloc((int)len+1);
if (s == NULL)
{
i=ERR_R_MALLOC_FAILURE;
goto err;
}
ret->type=V_ASN1_INTEGER;
if(len) {
if ((*p == 0) && (len != 1))
{
p++;
len--;
}
memcpy(s,p,(int)len);
p+=len;
}
if (ret->data != NULL) OPENSSL_free(ret->data);
ret->data=s;
ret->length=(int)len;
if (a != NULL) (*a)=ret;
*pp=p;
return(ret);
err:
OPENSSL_PUT_ERROR(ASN1, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_INTEGER_free(ret);
return(NULL);
}
int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
{
int j,k;
unsigned int i;
unsigned char buf[sizeof(long)+1];
long d;
a->type=V_ASN1_INTEGER;
if (a->length < (int)(sizeof(long)+1))
{
if (a->data != NULL)
OPENSSL_free(a->data);
if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL)
memset((char *)a->data,0,sizeof(long)+1);
}
if (a->data == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return(0);
}
d=v;
if (d < 0)
{
d= -d;
a->type=V_ASN1_NEG_INTEGER;
}
for (i=0; i<sizeof(long); i++)
{
if (d == 0) break;
buf[i]=(int)d&0xff;
d>>=8;
}
j=0;
for (k=i-1; k >=0; k--)
a->data[j++]=buf[k];
a->length=j;
return(1);
}
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
{
int neg=0,i;
long r=0;
if (a == NULL) return(0L);
i=a->type;
if (i == V_ASN1_NEG_INTEGER)
neg=1;
else if (i != V_ASN1_INTEGER)
return -1;
if (a->length > (int)sizeof(long))
{
/* hmm... a bit ugly, return all ones */
return -1;
}
if (a->data == NULL)
return 0;
for (i=0; i<a->length; i++)
{
r<<=8;
r|=(unsigned char)a->data[i];
}
if (neg) r= -r;
return(r);
}
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
{
ASN1_INTEGER *ret;
int len,j;
if (ai == NULL)
ret=M_ASN1_INTEGER_new();
else
ret=ai;
if (ret == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
goto err;
}
if (BN_is_negative(bn) && !BN_is_zero(bn))
ret->type = V_ASN1_NEG_INTEGER;
else ret->type=V_ASN1_INTEGER;
j=BN_num_bits(bn);
len=((j == 0)?0:((j/8)+1));
if (ret->length < len+4)
{
unsigned char *new_data=OPENSSL_realloc(ret->data, len+4);
if (!new_data)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->data=new_data;
}
ret->length=BN_bn2bin(bn,ret->data);
/* Correct zero case */
if(!ret->length)
{
ret->data[0] = 0;
ret->length = 1;
}
return(ret);
err:
if (ret != ai) M_ASN1_INTEGER_free(ret);
return(NULL);
}
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
{
BIGNUM *ret;
if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
else if(ai->type == V_ASN1_NEG_INTEGER)
BN_set_negative(ret, 1);
return(ret);
}

View File

@ -0,0 +1,390 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
static int traverse_string(const unsigned char *p, int len, int inform,
int (*rfunc)(unsigned long value, void *in), void *arg);
static int in_utf8(unsigned long value, void *arg);
static int out_utf8(unsigned long value, void *arg);
static int type_str(unsigned long value, void *arg);
static int cpy_asc(unsigned long value, void *arg);
static int cpy_bmp(unsigned long value, void *arg);
static int cpy_univ(unsigned long value, void *arg);
static int cpy_utf8(unsigned long value, void *arg);
static int is_printable(unsigned long value);
/* These functions take a string in UTF8, ASCII or multibyte form and
* a mask of permissible ASN1 string types. It then works out the minimal
* type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
* and creates a string of the correct type with the supplied data.
* Yes this is horrible: it has to be :-(
* The 'ncopy' form checks minimum and maximum size limits too.
*/
int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
int inform, unsigned long mask)
{
return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
}
int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
int inform, unsigned long mask,
long minsize, long maxsize)
{
int str_type;
int ret;
char free_out;
int outform, outlen = 0;
ASN1_STRING *dest;
unsigned char *p;
int nchar;
char strbuf[32];
int (*cpyfunc)(unsigned long,void *) = NULL;
if(len == -1) len = strlen((const char *)in);
if(!mask) mask = DIRSTRING_TYPE;
/* First do a string check and work out the number of characters */
switch(inform) {
case MBSTRING_BMP:
if(len & 1) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
return -1;
}
nchar = len >> 1;
break;
case MBSTRING_UNIV:
if(len & 3) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
return -1;
}
nchar = len >> 2;
break;
case MBSTRING_UTF8:
nchar = 0;
/* This counts the characters and does utf8 syntax checking */
ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
if(ret < 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING);
return -1;
}
break;
case MBSTRING_ASC:
nchar = len;
break;
default:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
return -1;
}
if((minsize > 0) && (nchar < minsize)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
ERR_add_error_data(2, "minsize=", strbuf);
return -1;
}
if((maxsize > 0) && (nchar > maxsize)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
ERR_add_error_data(2, "maxsize=", strbuf);
return -1;
}
/* Now work out minimal type (if any) */
if(traverse_string(in, len, inform, type_str, &mask) < 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
return -1;
}
/* Now work out output format and string type */
outform = MBSTRING_ASC;
if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING;
else if(mask & B_ASN1_IA5STRING) str_type = V_ASN1_IA5STRING;
else if(mask & B_ASN1_T61STRING) str_type = V_ASN1_T61STRING;
else if(mask & B_ASN1_BMPSTRING) {
str_type = V_ASN1_BMPSTRING;
outform = MBSTRING_BMP;
} else if(mask & B_ASN1_UNIVERSALSTRING) {
str_type = V_ASN1_UNIVERSALSTRING;
outform = MBSTRING_UNIV;
} else {
str_type = V_ASN1_UTF8STRING;
outform = MBSTRING_UTF8;
}
if(!out) return str_type;
if(*out) {
free_out = 0;
dest = *out;
if(dest->data) {
dest->length = 0;
OPENSSL_free(dest->data);
dest->data = NULL;
}
dest->type = str_type;
} else {
free_out = 1;
dest = ASN1_STRING_type_new(str_type);
if(!dest) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
*out = dest;
}
/* If both the same type just copy across */
if(inform == outform) {
if(!ASN1_STRING_set(dest, in, len)) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
return str_type;
}
/* Work out how much space the destination will need */
switch(outform) {
case MBSTRING_ASC:
outlen = nchar;
cpyfunc = cpy_asc;
break;
case MBSTRING_BMP:
outlen = nchar << 1;
cpyfunc = cpy_bmp;
break;
case MBSTRING_UNIV:
outlen = nchar << 2;
cpyfunc = cpy_univ;
break;
case MBSTRING_UTF8:
outlen = 0;
traverse_string(in, len, inform, out_utf8, &outlen);
cpyfunc = cpy_utf8;
break;
}
if(!(p = OPENSSL_malloc(outlen + 1))) {
if(free_out) ASN1_STRING_free(dest);
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return -1;
}
dest->length = outlen;
dest->data = p;
p[outlen] = 0;
traverse_string(in, len, inform, cpyfunc, &p);
return str_type;
}
/* This function traverses a string and passes the value of each character
* to an optional function along with a void * argument.
*/
static int traverse_string(const unsigned char *p, int len, int inform,
int (*rfunc)(unsigned long value, void *in), void *arg)
{
unsigned long value;
int ret;
while(len) {
if(inform == MBSTRING_ASC) {
value = *p++;
len--;
} else if(inform == MBSTRING_BMP) {
value = *p++ << 8;
value |= *p++;
len -= 2;
} else if(inform == MBSTRING_UNIV) {
value = ((unsigned long)*p++) << 24;
value |= ((unsigned long)*p++) << 16;
value |= *p++ << 8;
value |= *p++;
len -= 4;
} else {
ret = UTF8_getc(p, len, &value);
if(ret < 0) return -1;
len -= ret;
p += ret;
}
if(rfunc) {
ret = rfunc(value, arg);
if(ret <= 0) return ret;
}
}
return 1;
}
/* Various utility functions for traverse_string */
/* Just count number of characters */
static int in_utf8(unsigned long value, void *arg)
{
int *nchar;
nchar = arg;
(*nchar)++;
return 1;
}
/* Determine size of output as a UTF8 String */
static int out_utf8(unsigned long value, void *arg)
{
int *outlen;
outlen = arg;
*outlen += UTF8_putc(NULL, -1, value);
return 1;
}
/* Determine the "type" of a string: check each character against a
* supplied "mask".
*/
static int type_str(unsigned long value, void *arg)
{
unsigned long types;
types = *((unsigned long *)arg);
if((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
types &= ~B_ASN1_PRINTABLESTRING;
if((types & B_ASN1_IA5STRING) && (value > 127))
types &= ~B_ASN1_IA5STRING;
if((types & B_ASN1_T61STRING) && (value > 0xff))
types &= ~B_ASN1_T61STRING;
if((types & B_ASN1_BMPSTRING) && (value > 0xffff))
types &= ~B_ASN1_BMPSTRING;
if(!types) return -1;
*((unsigned long *)arg) = types;
return 1;
}
/* Copy one byte per character ASCII like strings */
static int cpy_asc(unsigned long value, void *arg)
{
unsigned char **p, *q;
p = arg;
q = *p;
*q = (unsigned char) value;
(*p)++;
return 1;
}
/* Copy two byte per character BMPStrings */
static int cpy_bmp(unsigned long value, void *arg)
{
unsigned char **p, *q;
p = arg;
q = *p;
*q++ = (unsigned char) ((value >> 8) & 0xff);
*q = (unsigned char) (value & 0xff);
*p += 2;
return 1;
}
/* Copy four byte per character UniversalStrings */
static int cpy_univ(unsigned long value, void *arg)
{
unsigned char **p, *q;
p = arg;
q = *p;
*q++ = (unsigned char) ((value >> 24) & 0xff);
*q++ = (unsigned char) ((value >> 16) & 0xff);
*q++ = (unsigned char) ((value >> 8) & 0xff);
*q = (unsigned char) (value & 0xff);
*p += 4;
return 1;
}
/* Copy to a UTF8String */
static int cpy_utf8(unsigned long value, void *arg)
{
unsigned char **p;
int ret;
p = arg;
/* We already know there is enough room so pass 0xff as the length */
ret = UTF8_putc(*p, 0xff, value);
*p += ret;
return 1;
}
/* Return 1 if the character is permitted in a PrintableString */
static int is_printable(unsigned long value)
{
int ch;
if(value > 0x7f) return 0;
ch = (int) value;
/* Note: we can't use 'isalnum' because certain accented
* characters may count as alphanumeric in some environments.
*/
if((ch >= 'a') && (ch <= 'z')) return 1;
if((ch >= 'A') && (ch <= 'Z')) return 1;
if((ch >= '0') && (ch <= '9')) return 1;
if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1;
return 0;
}

View File

@ -0,0 +1,412 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <limits.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
{
unsigned char *p;
int objsize;
if ((a == NULL) || (a->data == NULL)) return(0);
objsize = ASN1_object_size(0,a->length,V_ASN1_OBJECT);
if (pp == NULL) return objsize;
p= *pp;
ASN1_put_object(&p,0,a->length,V_ASN1_OBJECT,V_ASN1_UNIVERSAL);
memcpy(p,a->data,a->length);
p+=a->length;
*pp=p;
return(objsize);
}
int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
{
int i,first,len=0,c, use_bn;
char ftmp[24], *tmp = ftmp;
int tmpsize = sizeof ftmp;
const char *p;
unsigned long l;
BIGNUM *bl = NULL;
if (num == 0)
return(0);
else if (num == -1)
num=strlen(buf);
p=buf;
c= *(p++);
num--;
if ((c >= '0') && (c <= '2'))
{
first= c-'0';
}
else
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIRST_NUM_TOO_LARGE);
goto err;
}
if (num <= 0)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_SECOND_NUMBER);
goto err;
}
c= *(p++);
num--;
for (;;)
{
if (num <= 0) break;
if ((c != '.') && (c != ' '))
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_SEPARATOR);
goto err;
}
l=0;
use_bn = 0;
for (;;)
{
if (num <= 0) break;
num--;
c= *(p++);
if ((c == ' ') || (c == '.'))
break;
if ((c < '0') || (c > '9'))
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_DIGIT);
goto err;
}
if (!use_bn && l >= ((ULONG_MAX - 80) / 10L))
{
use_bn = 1;
if (!bl)
bl = BN_new();
if (!bl || !BN_set_word(bl, l))
goto err;
}
if (use_bn)
{
if (!BN_mul_word(bl, 10L)
|| !BN_add_word(bl, c-'0'))
goto err;
}
else
l=l*10L+(long)(c-'0');
}
if (len == 0)
{
if ((first < 2) && (l >= 40))
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE);
goto err;
}
if (use_bn)
{
if (!BN_add_word(bl, first * 40))
goto err;
}
else
l+=(long)first*40;
}
i=0;
if (use_bn)
{
int blsize;
blsize = BN_num_bits(bl);
blsize = (blsize + 6)/7;
if (blsize > tmpsize)
{
if (tmp != ftmp)
OPENSSL_free(tmp);
tmpsize = blsize + 32;
tmp = OPENSSL_malloc(tmpsize);
if (!tmp)
goto err;
}
while(blsize--)
tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
}
else
{
for (;;)
{
tmp[i++]=(unsigned char)l&0x7f;
l>>=7L;
if (l == 0L) break;
}
}
if (out != NULL)
{
if (len+i > olen)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
goto err;
}
while (--i > 0)
out[len++]=tmp[i]|0x80;
out[len++]=tmp[0];
}
else
len+=i;
}
if (tmp != ftmp)
OPENSSL_free(tmp);
if (bl)
BN_free(bl);
return(len);
err:
if (tmp != ftmp)
OPENSSL_free(tmp);
if (bl)
BN_free(bl);
return(0);
}
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
{
return OBJ_obj2txt(buf, buf_len, a, 0);
}
int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
{
char buf[80], *p = buf;
int i;
if ((a == NULL) || (a->data == NULL))
return(BIO_write(bp,"NULL",4));
i=i2t_ASN1_OBJECT(buf,sizeof buf,a);
if (i > (int)(sizeof(buf) - 1))
{
p = OPENSSL_malloc(i + 1);
if (!p)
return -1;
i2t_ASN1_OBJECT(p,i + 1,a);
}
if (i <= 0)
return BIO_write(bp, "<INVALID>", 9);
BIO_write(bp,p,i);
if (p != buf)
OPENSSL_free(p);
return(i);
}
ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long length)
{
const unsigned char *p;
long len;
int tag,xclass;
int inf,i;
ASN1_OBJECT *ret = NULL;
p= *pp;
inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
if (inf & 0x80)
{
i=ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != V_ASN1_OBJECT)
{
i=ASN1_R_EXPECTING_AN_OBJECT;
goto err;
}
ret = c2i_ASN1_OBJECT(a, &p, len);
if(ret) *pp = p;
return ret;
err:
OPENSSL_PUT_ERROR(ASN1, i);
return(NULL);
}
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long len)
{
ASN1_OBJECT *ret=NULL;
const unsigned char *p;
unsigned char *data;
int i, length;
/* Sanity check OID encoding.
* Need at least one content octet.
* MSB must be clear in the last octet.
* can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
*/
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
p[len - 1] & 0x80)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
return NULL;
}
/* Now 0 < len <= INT_MAX, so the cast is safe. */
length = (int)len;
for (i = 0; i < length; i++, p++)
{
if (*p == 0x80 && (!i || !(p[-1] & 0x80)))
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
return NULL;
}
}
/* only the ASN1_OBJECTs from the 'table' will have values
* for ->sn or ->ln */
if ((a == NULL) || ((*a) == NULL) ||
!((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC))
{
if ((ret=ASN1_OBJECT_new()) == NULL) return(NULL);
}
else ret=(*a);
p= *pp;
/* detach data from object */
data = (unsigned char *)ret->data;
ret->data = NULL;
/* once detached we can change it */
if ((data == NULL) || (ret->length < length))
{
ret->length=0;
if (data != NULL) OPENSSL_free(data);
data=(unsigned char *)OPENSSL_malloc(length);
if (data == NULL)
{ i=ERR_R_MALLOC_FAILURE; goto err; }
ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
}
memcpy(data,p,length);
/* reattach data to object, after which it remains const */
ret->data =data;
ret->length=length;
ret->sn=NULL;
ret->ln=NULL;
/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
p+=length;
if (a != NULL) (*a)=ret;
*pp=p;
return(ret);
err:
OPENSSL_PUT_ERROR(ASN1, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
ASN1_OBJECT_free(ret);
return(NULL);
}
ASN1_OBJECT *ASN1_OBJECT_new(void)
{
ASN1_OBJECT *ret;
ret=(ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
if (ret == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return(NULL);
}
ret->length=0;
ret->data=NULL;
ret->nid=0;
ret->sn=NULL;
ret->ln=NULL;
ret->flags=ASN1_OBJECT_FLAG_DYNAMIC;
return(ret);
}
void ASN1_OBJECT_free(ASN1_OBJECT *a)
{
if (a == NULL) return;
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS)
{
#ifndef CONST_STRICT /* disable purely for compile-time strict const checking. Doing this on a "real" compile will cause memory leaks */
if (a->sn != NULL) OPENSSL_free((void *)a->sn);
if (a->ln != NULL) OPENSSL_free((void *)a->ln);
#endif
a->sn=a->ln=NULL;
}
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA)
{
if (a->data != NULL) OPENSSL_free((void *)a->data);
a->data=NULL;
a->length=0;
}
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
OPENSSL_free(a);
}
ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
const char *sn, const char *ln)
{
ASN1_OBJECT o;
o.sn=sn;
o.ln=ln;
o.data=data;
o.nid=nid;
o.length=len;
o.flags=ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
ASN1_OBJECT_FLAG_DYNAMIC_DATA;
return(OBJ_dup(&o));
}

View File

@ -0,0 +1,70 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
{ return M_ASN1_OCTET_STRING_dup(x); }
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, const ASN1_OCTET_STRING *b)
{ return M_ASN1_OCTET_STRING_cmp(a, b); }
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, int len)
{ return M_ASN1_OCTET_STRING_set(x, d, len); }

View File

@ -0,0 +1,119 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
int ASN1_PRINTABLE_type(const unsigned char *s, int len)
{
int c;
int ia5=0;
int t61=0;
if (len <= 0) len= -1;
if (s == NULL) return(V_ASN1_PRINTABLESTRING);
while ((*s) && (len-- != 0))
{
c= *(s++);
if (!( ((c >= 'a') && (c <= 'z')) ||
((c >= 'A') && (c <= 'Z')) ||
(c == ' ') ||
((c >= '0') && (c <= '9')) ||
(c == ' ') || (c == '\'') ||
(c == '(') || (c == ')') ||
(c == '+') || (c == ',') ||
(c == '-') || (c == '.') ||
(c == '/') || (c == ':') ||
(c == '=') || (c == '?')))
ia5=1;
if (c&0x80)
t61=1;
}
if (t61) return(V_ASN1_T61STRING);
if (ia5) return(V_ASN1_IA5STRING);
return(V_ASN1_PRINTABLESTRING);
}
int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s)
{
int i;
unsigned char *p;
if (s->type != V_ASN1_UNIVERSALSTRING) return(0);
if ((s->length%4) != 0) return(0);
p=s->data;
for (i=0; i<s->length; i+=4)
{
if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0'))
break;
else
p+=4;
}
if (i < s->length) return(0);
p=s->data;
for (i=3; i<s->length; i+=4)
{
*(p++)=s->data[i];
}
*(p)='\0';
s->length/=4;
s->type=ASN1_PRINTABLE_type(s->data,s->length);
return(1);
}

View File

@ -0,0 +1,286 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <stdlib.h> /* For bsearch */
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
static void st_free(ASN1_STRING_TABLE *tbl);
/* This is the global mask for the mbstring functions: this is use to
* mask out certain types (such as BMPString and UTF8String) because
* certain software (e.g. Netscape) has problems with them.
*/
static unsigned long global_mask = B_ASN1_UTF8STRING;
void ASN1_STRING_set_default_mask(unsigned long mask)
{
global_mask = mask;
}
unsigned long ASN1_STRING_get_default_mask(void)
{
return global_mask;
}
/* This function sets the default to various "flavours" of configuration.
* based on an ASCII string. Currently this is:
* MASK:XXXX : a numerical mask value.
* nobmp : Don't use BMPStrings (just Printable, T61).
* pkix : PKIX recommendation in RFC2459.
* utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
* default: the default value, Printable, T61, BMP.
*/
int ASN1_STRING_set_default_mask_asc(const char *p)
{
unsigned long mask;
char *end;
if(!strncmp(p, "MASK:", 5)) {
if(!p[5]) return 0;
mask = strtoul(p + 5, &end, 0);
if(*end) return 0;
} else if(!strcmp(p, "nombstr"))
mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING));
else if(!strcmp(p, "pkix"))
mask = ~((unsigned long)B_ASN1_T61STRING);
else if(!strcmp(p, "utf8only")) mask = B_ASN1_UTF8STRING;
else if(!strcmp(p, "default"))
mask = 0xFFFFFFFFL;
else return 0;
ASN1_STRING_set_default_mask(mask);
return 1;
}
/* The following function generates an ASN1_STRING based on limits in a table.
* Frequently the types and length of an ASN1_STRING are restricted by a
* corresponding OID. For example certificates and certificate requests.
*/
ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in,
int inlen, int inform, int nid)
{
ASN1_STRING_TABLE *tbl;
ASN1_STRING *str = NULL;
unsigned long mask;
int ret;
if(!out) out = &str;
tbl = ASN1_STRING_TABLE_get(nid);
if(tbl) {
mask = tbl->mask;
if(!(tbl->flags & STABLE_NO_MASK)) mask &= global_mask;
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
tbl->minsize, tbl->maxsize);
} else ret = ASN1_mbstring_copy(out, in, inlen, inform, DIRSTRING_TYPE & global_mask);
if(ret <= 0) return NULL;
return *out;
}
/* Now the tables and helper functions for the string table:
*/
/* size limits: this stuff is taken straight from RFC3280 */
#define ub_name 32768
#define ub_common_name 64
#define ub_locality_name 128
#define ub_state_name 128
#define ub_organization_name 64
#define ub_organization_unit_name 64
#define ub_title 64
#define ub_email_address 128
#define ub_serial_number 64
/* This table must be kept in NID order */
static const ASN1_STRING_TABLE tbl_standard[] = {
{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE, 0},
{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING, STABLE_NO_MASK},
{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
{NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
};
static int sk_table_cmp(const ASN1_STRING_TABLE **a,
const ASN1_STRING_TABLE **b)
{
return (*a)->nid - (*b)->nid;
}
static int table_cmp(const void *in_a, const void *in_b)
{
const ASN1_STRING_TABLE *a = in_a;
const ASN1_STRING_TABLE *b = in_b;
return a->nid - b->nid;
}
ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
{
int found;
size_t idx;
ASN1_STRING_TABLE *ttmp;
ASN1_STRING_TABLE fnd;
fnd.nid = nid;
ttmp = bsearch(&fnd, tbl_standard, sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE), sizeof(ASN1_STRING_TABLE), table_cmp);
if(ttmp) return ttmp;
if(!stable) return NULL;
found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
if (!found) return NULL;
return sk_ASN1_STRING_TABLE_value(stable, idx);
}
int ASN1_STRING_TABLE_add(int nid,
long minsize, long maxsize, unsigned long mask,
unsigned long flags)
{
ASN1_STRING_TABLE *tmp;
char new_nid = 0;
flags &= ~STABLE_FLAGS_MALLOC;
if(!stable) stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
if(!stable) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
if(!(tmp = ASN1_STRING_TABLE_get(nid))) {
tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
if(!tmp) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return 0;
}
tmp->flags = flags | STABLE_FLAGS_MALLOC;
tmp->nid = nid;
new_nid = 1;
} else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
if(minsize != -1) tmp->minsize = minsize;
if(maxsize != -1) tmp->maxsize = maxsize;
tmp->mask = mask;
if(new_nid) sk_ASN1_STRING_TABLE_push(stable, tmp);
return 1;
}
void ASN1_STRING_TABLE_cleanup(void)
{
STACK_OF(ASN1_STRING_TABLE) *tmp;
tmp = stable;
if(!tmp) return;
stable = NULL;
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
}
static void st_free(ASN1_STRING_TABLE *tbl)
{
if(tbl->flags & STABLE_FLAGS_MALLOC) OPENSSL_free(tbl);
}
#ifdef STRING_TABLE_TEST
int
main(void)
{
ASN1_STRING_TABLE *tmp;
int i, last_nid = -1;
for (tmp = tbl_standard, i = 0;
i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++)
{
if (tmp->nid < last_nid)
{
last_nid = 0;
break;
}
last_nid = tmp->nid;
}
if (last_nid != 0)
{
printf("Table order OK\n");
exit(0);
}
for (tmp = tbl_standard, i = 0;
i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++)
printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
OBJ_nid2ln(tmp->nid));
return 0;
}
#endif

View File

@ -0,0 +1,221 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <time.h>
#include <openssl/asn1t.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/time_support.h>
#include "asn1_locl.h"
/* This is an implementation of the ASN1 Time structure which is:
* Time ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
* written by Steve Henson.
*/
IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
#if 0
int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp)
{
if(a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME)
return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
a->type ,V_ASN1_UNIVERSAL));
OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_TIME);
return -1;
}
#endif
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
{
return ASN1_TIME_adj(s, t, 0, 0);
}
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
int offset_day, long offset_sec)
{
struct tm *ts;
struct tm data;
ts=OPENSSL_gmtime(&t,&data);
if (ts == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME);
return NULL;
}
if (offset_day || offset_sec)
{
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
return NULL;
}
if((ts->tm_year >= 50) && (ts->tm_year < 150))
return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
}
int ASN1_TIME_check(ASN1_TIME *t)
{
if (t->type == V_ASN1_GENERALIZEDTIME)
return ASN1_GENERALIZEDTIME_check(t);
else if (t->type == V_ASN1_UTCTIME)
return ASN1_UTCTIME_check(t);
return 0;
}
/* Convert an ASN1_TIME structure to GeneralizedTime */
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
{
ASN1_GENERALIZEDTIME *ret;
char *str;
int newlen;
if (!ASN1_TIME_check(t)) return NULL;
if (!out || !*out)
{
if (!(ret = ASN1_GENERALIZEDTIME_new ()))
return NULL;
if (out) *out = ret;
}
else ret = *out;
/* If already GeneralizedTime just copy across */
if (t->type == V_ASN1_GENERALIZEDTIME)
{
if(!ASN1_STRING_set(ret, t->data, t->length))
return NULL;
return ret;
}
/* grow the string */
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
return NULL;
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
newlen = t->length + 2 + 1;
str = (char *)ret->data;
/* Work out the century and prepend */
if (t->data[0] >= '5') BUF_strlcpy(str, "19", newlen);
else BUF_strlcpy(str, "20", newlen);
BUF_strlcat(str, (char *)t->data, newlen);
return ret;
}
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
{
ASN1_TIME t;
t.length = strlen(str);
t.data = (unsigned char *)str;
t.flags = 0;
t.type = V_ASN1_UTCTIME;
if (!ASN1_TIME_check(&t))
{
t.type = V_ASN1_GENERALIZEDTIME;
if (!ASN1_TIME_check(&t))
return 0;
}
if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
return 0;
return 1;
}
static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t)
{
if (t == NULL)
{
time_t now_t;
time(&now_t);
if (OPENSSL_gmtime(&now_t, tm))
return 1;
return 0;
}
if (t->type == V_ASN1_UTCTIME)
return asn1_utctime_to_tm(tm, t);
else if (t->type == V_ASN1_GENERALIZEDTIME)
return asn1_generalizedtime_to_tm(tm, t);
return 0;
}
int ASN1_TIME_diff(int *pday, int *psec,
const ASN1_TIME *from, const ASN1_TIME *to)
{
struct tm tm_from, tm_to;
if (!asn1_time_to_tm(&tm_from, from))
return 0;
if (!asn1_time_to_tm(&tm_to, to))
return 0;
return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
}

View File

@ -0,0 +1,160 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
int ASN1_TYPE_get(ASN1_TYPE *a)
{
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
return(a->type);
else
return(0);
}
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
{
if (a->value.ptr != NULL)
{
ASN1_TYPE **tmp_a = &a;
ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
}
a->type=type;
if (type == V_ASN1_BOOLEAN)
a->value.boolean = value ? 0xff : 0;
else
a->value.ptr=value;
}
int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
{
if (!value || (type == V_ASN1_BOOLEAN))
{
void *p = (void *)value;
ASN1_TYPE_set(a, type, p);
}
else if (type == V_ASN1_OBJECT)
{
ASN1_OBJECT *odup;
odup = OBJ_dup(value);
if (!odup)
return 0;
ASN1_TYPE_set(a, type, odup);
}
else
{
ASN1_STRING *sdup;
sdup = ASN1_STRING_dup(value);
if (!sdup)
return 0;
ASN1_TYPE_set(a, type, sdup);
}
return 1;
}
/* Returns 0 if they are equal, != 0 otherwise. */
int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
{
int result = -1;
if (!a || !b || a->type != b->type) return -1;
switch (a->type)
{
case V_ASN1_OBJECT:
result = OBJ_cmp(a->value.object, b->value.object);
break;
case V_ASN1_NULL:
result = 0; /* They do not have content. */
break;
case V_ASN1_BOOLEAN:
result = a->value.boolean - b->value.boolean;
break;
case V_ASN1_INTEGER:
case V_ASN1_NEG_INTEGER:
case V_ASN1_ENUMERATED:
case V_ASN1_NEG_ENUMERATED:
case V_ASN1_BIT_STRING:
case V_ASN1_OCTET_STRING:
case V_ASN1_SEQUENCE:
case V_ASN1_SET:
case V_ASN1_NUMERICSTRING:
case V_ASN1_PRINTABLESTRING:
case V_ASN1_T61STRING:
case V_ASN1_VIDEOTEXSTRING:
case V_ASN1_IA5STRING:
case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME:
case V_ASN1_GRAPHICSTRING:
case V_ASN1_VISIBLESTRING:
case V_ASN1_GENERALSTRING:
case V_ASN1_UNIVERSALSTRING:
case V_ASN1_BMPSTRING:
case V_ASN1_UTF8STRING:
case V_ASN1_OTHER:
default:
result = ASN1_STRING_cmp((ASN1_STRING *) a->value.ptr,
(ASN1_STRING *) b->value.ptr);
break;
}
return result;
}

View File

@ -0,0 +1,342 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <time.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/time_support.h>
#if 0
int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **pp)
{
return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
V_ASN1_UTCTIME,V_ASN1_UNIVERSAL));
}
ASN1_UTCTIME *d2i_ASN1_UTCTIME(ASN1_UTCTIME **a, unsigned char **pp,
long length)
{
ASN1_UTCTIME *ret=NULL;
ret=(ASN1_UTCTIME *)d2i_ASN1_bytes((ASN1_STRING **)a,pp,length,
V_ASN1_UTCTIME,V_ASN1_UNIVERSAL);
if (ret == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_NESTED_ASN1_ERROR);
return(NULL);
}
if (!ASN1_UTCTIME_check(ret))
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT);
goto err;
}
return(ret);
err:
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_UTCTIME_free(ret);
return(NULL);
}
#endif
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
{
static const int min[8]={ 0, 1, 1, 0, 0, 0, 0, 0};
static const int max[8]={99,12,31,23,59,59,12,59};
char *a;
int n,i,l,o;
if (d->type != V_ASN1_UTCTIME) return(0);
l=d->length;
a=(char *)d->data;
o=0;
if (l < 11) goto err;
for (i=0; i<6; i++)
{
if ((i == 5) && ((a[o] == 'Z') ||
(a[o] == '+') || (a[o] == '-')))
{
i++;
if (tm)
tm->tm_sec = 0;
break;
}
if ((a[o] < '0') || (a[o] > '9')) goto err;
n= a[o]-'0';
if (++o > l) goto err;
if ((a[o] < '0') || (a[o] > '9')) goto err;
n=(n*10)+ a[o]-'0';
if (++o > l) goto err;
if ((n < min[i]) || (n > max[i])) goto err;
if (tm)
{
switch(i)
{
case 0:
tm->tm_year = n < 50 ? n + 100 : n;
break;
case 1:
tm->tm_mon = n - 1;
break;
case 2:
tm->tm_mday = n;
break;
case 3:
tm->tm_hour = n;
break;
case 4:
tm->tm_min = n;
break;
case 5:
tm->tm_sec = n;
break;
}
}
}
if (a[o] == 'Z')
o++;
else if ((a[o] == '+') || (a[o] == '-'))
{
int offsign = a[o] == '-' ? -1 : 1, offset = 0;
o++;
if (o+4 > l) goto err;
for (i=6; i<8; i++)
{
if ((a[o] < '0') || (a[o] > '9')) goto err;
n= a[o]-'0';
o++;
if ((a[o] < '0') || (a[o] > '9')) goto err;
n=(n*10)+ a[o]-'0';
if ((n < min[i]) || (n > max[i])) goto err;
if (tm)
{
if (i == 6)
offset = n * 3600;
else if (i == 7)
offset += n * 60;
}
o++;
}
if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
return 0;
}
return o == l;
err:
return 0;
}
int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
{
return asn1_utctime_to_tm(NULL, d);
}
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
{
ASN1_UTCTIME t;
t.type=V_ASN1_UTCTIME;
t.length=strlen(str);
t.data=(unsigned char *)str;
if (ASN1_UTCTIME_check(&t))
{
if (s != NULL)
{
if (!ASN1_STRING_set((ASN1_STRING *)s,
(unsigned char *)str,t.length))
return 0;
s->type = V_ASN1_UTCTIME;
}
return(1);
}
else
return(0);
}
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
{
return ASN1_UTCTIME_adj(s, t, 0, 0);
}
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
int offset_day, long offset_sec)
{
char *p;
struct tm *ts;
struct tm data;
size_t len = 20;
int free_s = 0;
if (s == NULL)
{
free_s = 1;
s=M_ASN1_UTCTIME_new();
}
if (s == NULL)
goto err;
ts=OPENSSL_gmtime(&t, &data);
if (ts == NULL)
goto err;
if (offset_day || offset_sec)
{
if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
goto err;
}
if((ts->tm_year < 50) || (ts->tm_year >= 150))
goto err;
p=(char *)s->data;
if ((p == NULL) || ((size_t)s->length < len))
{
p=OPENSSL_malloc(len);
if (p == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
if (s->data != NULL)
OPENSSL_free(s->data);
s->data=(unsigned char *)p;
}
BIO_snprintf(p,len,"%02d%02d%02d%02d%02d%02dZ",ts->tm_year%100,
ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
s->length=strlen(p);
s->type=V_ASN1_UTCTIME;
return(s);
err:
if (free_s && s)
M_ASN1_UTCTIME_free(s);
return NULL;
}
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
{
struct tm stm, ttm;
int day, sec;
if (!asn1_utctime_to_tm(&stm, s))
return -2;
if (!OPENSSL_gmtime(&t, &ttm))
return -2;
if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
return -2;
if (day > 0)
return 1;
if (day < 0)
return -1;
if (sec > 0)
return 1;
if (sec < 0)
return -1;
return 0;
}
#if 0
time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
{
struct tm tm;
int offset;
memset(&tm,'\0',sizeof tm);
#define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
tm.tm_year=g2(s->data);
if(tm.tm_year < 50)
tm.tm_year+=100;
tm.tm_mon=g2(s->data+2)-1;
tm.tm_mday=g2(s->data+4);
tm.tm_hour=g2(s->data+6);
tm.tm_min=g2(s->data+8);
tm.tm_sec=g2(s->data+10);
if(s->data[12] == 'Z')
offset=0;
else
{
offset=g2(s->data+13)*60+g2(s->data+15);
if(s->data[12] == '-')
offset= -offset;
}
#undef g2
return mktime(&tm)-offset*60; /* FIXME: mktime assumes the current timezone
* instead of UTC, and unless we rewrite OpenSSL
* in Lisp we cannot locally change the timezone
* without possibly interfering with other parts
* of the program. timegm, which uses UTC, is
* non-standard.
* Also time_t is inappropriate for general
* UTC times because it may a 32 bit type. */
}
#endif

View File

@ -0,0 +1,210 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
/* UTF8 utilities */
/* This parses a UTF8 string one character at a time. It is passed a pointer
* to the string and the length of the string. It sets 'value' to the value of
* the current character. It returns the number of characters read or a
* negative error code:
* -1 = string too short
* -2 = illegal character
* -3 = subsequent characters not of the form 10xxxxxx
* -4 = character encoded incorrectly (not minimal length).
*/
int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
{
const unsigned char *p;
unsigned long value;
int ret;
if(len <= 0) return 0;
p = str;
/* Check syntax and work out the encoded value (if correct) */
if((*p & 0x80) == 0) {
value = *p++ & 0x7f;
ret = 1;
} else if((*p & 0xe0) == 0xc0) {
if(len < 2) return -1;
if((p[1] & 0xc0) != 0x80) return -3;
value = (*p++ & 0x1f) << 6;
value |= *p++ & 0x3f;
if(value < 0x80) return -4;
ret = 2;
} else if((*p & 0xf0) == 0xe0) {
if(len < 3) return -1;
if( ((p[1] & 0xc0) != 0x80)
|| ((p[2] & 0xc0) != 0x80) ) return -3;
value = (*p++ & 0xf) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if(value < 0x800) return -4;
ret = 3;
} else if((*p & 0xf8) == 0xf0) {
if(len < 4) return -1;
if( ((p[1] & 0xc0) != 0x80)
|| ((p[2] & 0xc0) != 0x80)
|| ((p[3] & 0xc0) != 0x80) ) return -3;
value = ((unsigned long)(*p++ & 0x7)) << 18;
value |= (*p++ & 0x3f) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if(value < 0x10000) return -4;
ret = 4;
} else if((*p & 0xfc) == 0xf8) {
if(len < 5) return -1;
if( ((p[1] & 0xc0) != 0x80)
|| ((p[2] & 0xc0) != 0x80)
|| ((p[3] & 0xc0) != 0x80)
|| ((p[4] & 0xc0) != 0x80) ) return -3;
value = ((unsigned long)(*p++ & 0x3)) << 24;
value |= ((unsigned long)(*p++ & 0x3f)) << 18;
value |= ((unsigned long)(*p++ & 0x3f)) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if(value < 0x200000) return -4;
ret = 5;
} else if((*p & 0xfe) == 0xfc) {
if(len < 6) return -1;
if( ((p[1] & 0xc0) != 0x80)
|| ((p[2] & 0xc0) != 0x80)
|| ((p[3] & 0xc0) != 0x80)
|| ((p[4] & 0xc0) != 0x80)
|| ((p[5] & 0xc0) != 0x80) ) return -3;
value = ((unsigned long)(*p++ & 0x1)) << 30;
value |= ((unsigned long)(*p++ & 0x3f)) << 24;
value |= ((unsigned long)(*p++ & 0x3f)) << 18;
value |= ((unsigned long)(*p++ & 0x3f)) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if(value < 0x4000000) return -4;
ret = 6;
} else return -2;
*val = value;
return ret;
}
/* This takes a character 'value' and writes the UTF8 encoded value in
* 'str' where 'str' is a buffer containing 'len' characters. Returns
* the number of characters written or -1 if 'len' is too small. 'str' can
* be set to NULL in which case it just returns the number of characters.
* It will need at most 6 characters.
*/
int UTF8_putc(unsigned char *str, int len, unsigned long value)
{
if(!str) len = 6; /* Maximum we will need */
else if(len <= 0) return -1;
if(value < 0x80) {
if(str) *str = (unsigned char)value;
return 1;
}
if(value < 0x800) {
if(len < 2) return -1;
if(str) {
*str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 2;
}
if(value < 0x10000) {
if(len < 3) return -1;
if(str) {
*str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 3;
}
if(value < 0x200000) {
if(len < 4) return -1;
if(str) {
*str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 4;
}
if(value < 0x4000000) {
if(len < 5) return -1;
if(str) {
*str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 5;
}
if(len < 6) return -1;
if(str) {
*str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
*str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
*str = (unsigned char)((value & 0x3f) | 0x80);
}
return 6;
}

View File

@ -0,0 +1,510 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <limits.h>
#include <string.h>
#include <openssl/asn1_mac.h>
#include <openssl/err.h>
#include <openssl/mem.h>
/* Used in asn1_mac.h.
* TODO(davidben): Remove this once asn1_mac.h is gone or trimmed. */
OPENSSL_DECLARE_ERROR_REASON(ASN1, MALLOC_FAILURE);
/* Cross-module errors from crypto/x509/i2d_pr.c */
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE);
/* Cross-module errors from crypto/x509/asn1_gen.c.
* TODO(davidben): Remove these once asn1_gen.c is gone. */
OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED);
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT);
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN);
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT);
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX);
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG);
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER);
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING);
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE);
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT);
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE);
OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT);
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER);
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER);
OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR);
OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE);
OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT);
OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT);
OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG);
OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT);
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT);
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG);
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE);
static int asn1_get_length(const unsigned char **pp,int *inf,long *rl,int max);
static void asn1_put_length(unsigned char **pp, int length);
static int _asn1_check_infinite_end(const unsigned char **p, long len)
{
/* If there is 0 or 1 byte left, the length check should pick
* things up */
if (len <= 0)
return(1);
else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0))
{
(*p)+=2;
return(1);
}
return(0);
}
int ASN1_check_infinite_end(unsigned char **p, long len)
{
return _asn1_check_infinite_end((const unsigned char **)p, len);
}
int ASN1_const_check_infinite_end(const unsigned char **p, long len)
{
return _asn1_check_infinite_end(p, len);
}
int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
int *pclass, long omax)
{
int i,ret;
long l;
const unsigned char *p= *pp;
int tag,xclass,inf;
long max=omax;
if (!max) goto err;
ret=(*p&V_ASN1_CONSTRUCTED);
xclass=(*p&V_ASN1_PRIVATE);
i= *p&V_ASN1_PRIMITIVE_TAG;
if (i == V_ASN1_PRIMITIVE_TAG)
{ /* high-tag */
p++;
if (--max == 0) goto err;
l=0;
while (*p&0x80)
{
l<<=7L;
l|= *(p++)&0x7f;
if (--max == 0) goto err;
if (l > (INT_MAX >> 7L)) goto err;
}
l<<=7L;
l|= *(p++)&0x7f;
tag=(int)l;
if (--max == 0) goto err;
}
else
{
tag=i;
p++;
if (--max == 0) goto err;
}
*ptag=tag;
*pclass=xclass;
if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err;
if (inf && !(ret & V_ASN1_CONSTRUCTED))
goto err;
#if 0
fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
(int)p,*plength,omax,(int)*pp,(int)(p+ *plength),
(int)(omax+ *pp));
#endif
if (*plength > (omax - (p - *pp)))
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
/* Set this so that even if things are not long enough
* the values are set correctly */
ret|=0x80;
}
*pp=p;
return(ret|inf);
err:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
return(0x80);
}
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max)
{
const unsigned char *p= *pp;
unsigned long ret=0;
unsigned int i;
if (max-- < 1) return(0);
if (*p == 0x80)
{
*inf=1;
ret=0;
p++;
}
else
{
*inf=0;
i= *p&0x7f;
if (*(p++) & 0x80)
{
if (i > sizeof(long))
return 0;
if (max-- == 0) return(0);
while (i-- > 0)
{
ret<<=8L;
ret|= *(p++);
if (max-- == 0) return(0);
}
}
else
ret=i;
}
if (ret > LONG_MAX)
return 0;
*pp=p;
*rl=(long)ret;
return(1);
}
/* class 0 is constructed
* constructed == 2 for indefinite length constructed */
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
int xclass)
{
unsigned char *p= *pp;
int i, ttag;
i=(constructed)?V_ASN1_CONSTRUCTED:0;
i|=(xclass&V_ASN1_PRIVATE);
if (tag < 31)
*(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG);
else
{
*(p++)=i|V_ASN1_PRIMITIVE_TAG;
for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7;
ttag = i;
while(i-- > 0)
{
p[i] = tag & 0x7f;
if(i != (ttag - 1)) p[i] |= 0x80;
tag >>= 7;
}
p += ttag;
}
if (constructed == 2)
*(p++)=0x80;
else
asn1_put_length(&p,length);
*pp=p;
}
int ASN1_put_eoc(unsigned char **pp)
{
unsigned char *p = *pp;
*p++ = 0;
*p++ = 0;
*pp = p;
return 2;
}
static void asn1_put_length(unsigned char **pp, int length)
{
unsigned char *p= *pp;
int i,l;
if (length <= 127)
*(p++)=(unsigned char)length;
else
{
l=length;
for (i=0; l > 0; i++)
l>>=8;
*(p++)=i|0x80;
l=i;
while (i-- > 0)
{
p[i]=length&0xff;
length>>=8;
}
p+=l;
}
*pp=p;
}
int ASN1_object_size(int constructed, int length, int tag)
{
int ret;
ret=length;
ret++;
if (tag >= 31)
{
while (tag > 0)
{
tag>>=7;
ret++;
}
}
if (constructed == 2)
return ret + 3;
ret++;
if (length > 127)
{
while (length > 0)
{
length>>=8;
ret++;
}
}
return(ret);
}
static int _asn1_Finish(ASN1_const_CTX *c)
{
if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos))
{
if (!ASN1_const_check_infinite_end(&c->p,c->slen))
{
c->error=ASN1_R_MISSING_ASN1_EOS;
return(0);
}
}
if ( ((c->slen != 0) && !(c->inf & 1)) ||
((c->slen < 0) && (c->inf & 1)))
{
c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
return(0);
}
return(1);
}
int asn1_Finish(ASN1_CTX *c)
{
return _asn1_Finish((ASN1_const_CTX *)c);
}
int asn1_const_Finish(ASN1_const_CTX *c)
{
return _asn1_Finish(c);
}
int asn1_GetSequence(ASN1_const_CTX *c, long *length)
{
const unsigned char *q;
q=c->p;
c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass),
*length);
if (c->inf & 0x80)
{
c->error=ASN1_R_BAD_GET_ASN1_OBJECT_CALL;
return(0);
}
if (c->tag != V_ASN1_SEQUENCE)
{
c->error=ASN1_R_EXPECTING_AN_ASN1_SEQUENCE;
return(0);
}
(*length)-=(c->p-q);
if (c->max && (*length < 0))
{
c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
return(0);
}
if (c->inf == (1|V_ASN1_CONSTRUCTED))
c->slen= *length+ *(c->pp)-c->p;
c->eos=0;
return(1);
}
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
{
if (str == NULL)
return 0;
dst->type = str->type;
if (!ASN1_STRING_set(dst,str->data,str->length))
return 0;
dst->flags = str->flags;
return 1;
}
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
{
ASN1_STRING *ret;
if (!str)
return NULL;
ret=ASN1_STRING_new();
if (!ret)
return NULL;
if (!ASN1_STRING_copy(ret,str))
{
ASN1_STRING_free(ret);
return NULL;
}
return ret;
}
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
{
unsigned char *c;
const char *data=_data;
if (len < 0)
{
if (data == NULL)
return(0);
else
len=strlen(data);
}
if ((str->length < len) || (str->data == NULL))
{
c=str->data;
if (c == NULL)
str->data=OPENSSL_malloc(len+1);
else
str->data=OPENSSL_realloc(c,len+1);
if (str->data == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
str->data=c;
return(0);
}
}
str->length=len;
if (data != NULL)
{
memcpy(str->data,data,len);
/* an allowance for strings :-) */
str->data[len]='\0';
}
return(1);
}
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
{
if (str->data)
OPENSSL_free(str->data);
str->data = data;
str->length = len;
}
ASN1_STRING *ASN1_STRING_new(void)
{
return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
}
ASN1_STRING *ASN1_STRING_type_new(int type)
{
ASN1_STRING *ret;
ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
if (ret == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return(NULL);
}
ret->length=0;
ret->type=type;
ret->data=NULL;
ret->flags=0;
return(ret);
}
void ASN1_STRING_free(ASN1_STRING *a)
{
if (a == NULL) return;
if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
OPENSSL_free(a->data);
OPENSSL_free(a);
}
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
{
int i;
i=(a->length-b->length);
if (i == 0)
{
i=memcmp(a->data,b->data,a->length);
if (i == 0)
return(a->type-b->type);
else
return(i);
}
else
return(i);
}
int ASN1_STRING_length(const ASN1_STRING *x)
{ return M_ASN1_STRING_length(x); }
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
{ M_ASN1_STRING_length_set(x, len); return; }
int ASN1_STRING_type(ASN1_STRING *x)
{ return M_ASN1_STRING_type(x); }
unsigned char * ASN1_STRING_data(ASN1_STRING *x)
{ return M_ASN1_STRING_data(x); }

View File

@ -0,0 +1,73 @@
/* asn1t.h */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
/* Internal ASN1 structures and functions: not for application use */
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
/* ASN1 print context structure */
struct asn1_pctx_st
{
unsigned long flags;
unsigned long nm_flags;
unsigned long cert_flags;
unsigned long oid_flags;
unsigned long str_flags;
} /* ASN1_PCTX */;

View File

@ -0,0 +1,435 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/mem.h>
static int asn1_print_info(BIO *bp, int tag, int xclass,int constructed,
int indent);
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
int offset, int depth, int indent, int dump);
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
int indent)
{
static const char fmt[]="%-18s";
char str[128];
const char *p;
if (constructed & V_ASN1_CONSTRUCTED)
p="cons: ";
else
p="prim: ";
if (BIO_write(bp,p,6) < 6) goto err;
BIO_indent(bp,indent,128);
p=str;
if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
BIO_snprintf(str,sizeof str,"priv [ %d ] ",tag);
else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
BIO_snprintf(str,sizeof str,"cont [ %d ]",tag);
else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
BIO_snprintf(str,sizeof str,"appl [ %d ]",tag);
else if (tag > 30)
BIO_snprintf(str,sizeof str,"<ASN1 %d>",tag);
else
p = ASN1_tag2str(tag);
if (BIO_printf(bp,fmt,p) <= 0)
goto err;
return(1);
err:
return(0);
}
int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
{
return(asn1_parse2(bp,&pp,len,0,0,indent,0));
}
int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int dump)
{
return(asn1_parse2(bp,&pp,len,0,0,indent,dump));
}
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset,
int depth, int indent, int dump)
{
const unsigned char *p,*ep,*tot,*op,*opp;
long len;
int tag,xclass,ret=0;
int nl,hl,j,r;
ASN1_OBJECT *o=NULL;
ASN1_OCTET_STRING *os=NULL;
/* ASN1_BMPSTRING *bmp=NULL;*/
int dump_indent;
#if 0
dump_indent = indent;
#else
dump_indent = 6; /* Because we know BIO_dump_indent() */
#endif
p= *pp;
tot=p+length;
op=p-1;
while ((p < tot) && (op < p))
{
op=p;
j=ASN1_get_object(&p,&len,&tag,&xclass,length);
#ifdef LINT
j=j;
#endif
if (j & 0x80)
{
if (BIO_puts(bp, "Error in encoding\n") <= 0)
goto end;
ret=0;
goto end;
}
hl=(p-op);
length-=hl;
/* if j == 0x21 it is a constructed indefinite length object */
if (BIO_printf(bp,"%5ld:",(long)offset+(long)(op- *pp))
<= 0) goto end;
if (j != (V_ASN1_CONSTRUCTED | 1))
{
if (BIO_printf(bp,"d=%-2d hl=%ld l=%4ld ",
depth,(long)hl,len) <= 0)
goto end;
}
else
{
if (BIO_printf(bp,"d=%-2d hl=%ld l=inf ",
depth,(long)hl) <= 0)
goto end;
}
if (!asn1_print_info(bp,tag,xclass,j,(indent)?depth:0))
goto end;
if (j & V_ASN1_CONSTRUCTED)
{
ep=p+len;
if (BIO_puts(bp, "\n") <= 0) goto end;
if (len > length)
{
BIO_printf(bp,
"length is greater than %ld\n",length);
ret=0;
goto end;
}
if ((j == 0x21) && (len == 0))
{
for (;;)
{
r=asn1_parse2(bp,&p,(long)(tot-p),
offset+(p - *pp),depth+1,
indent,dump);
if (r == 0) { ret=0; goto end; }
if ((r == 2) || (p >= tot)) break;
}
}
else
while (p < ep)
{
r=asn1_parse2(bp,&p,(long)len,
offset+(p - *pp),depth+1,
indent,dump);
if (r == 0) { ret=0; goto end; }
}
}
else if (xclass != 0)
{
p+=len;
if (BIO_puts(bp, "\n") <= 0) goto end;
}
else
{
nl=0;
if ( (tag == V_ASN1_PRINTABLESTRING) ||
(tag == V_ASN1_T61STRING) ||
(tag == V_ASN1_IA5STRING) ||
(tag == V_ASN1_VISIBLESTRING) ||
(tag == V_ASN1_NUMERICSTRING) ||
(tag == V_ASN1_UTF8STRING) ||
(tag == V_ASN1_UTCTIME) ||
(tag == V_ASN1_GENERALIZEDTIME))
{
if (BIO_puts(bp, ":") <= 0) goto end;
if ((len > 0) &&
BIO_write(bp,(const char *)p,(int)len)
!= (int)len)
goto end;
}
else if (tag == V_ASN1_OBJECT)
{
opp=op;
if (d2i_ASN1_OBJECT(&o,&opp,len+hl) != NULL)
{
if (BIO_puts(bp, ":") <= 0) goto end;
i2a_ASN1_OBJECT(bp,o);
}
else
{
if (BIO_puts(bp, ":BAD OBJECT") <= 0)
goto end;
}
}
else if (tag == V_ASN1_BOOLEAN)
{
int ii;
opp=op;
ii=d2i_ASN1_BOOLEAN(NULL,&opp,len+hl);
if (ii < 0)
{
if (BIO_puts(bp, "Bad boolean\n") <= 0)
goto end;
}
BIO_printf(bp,":%d",ii);
}
else if (tag == V_ASN1_BMPSTRING)
{
/* do the BMP thang */
}
else if (tag == V_ASN1_OCTET_STRING)
{
int i,printable=1;
opp=op;
os=d2i_ASN1_OCTET_STRING(NULL,&opp,len+hl);
if (os != NULL && os->length > 0)
{
opp = os->data;
/* testing whether the octet string is
* printable */
for (i=0; i<os->length; i++)
{
if (( (opp[i] < ' ') &&
(opp[i] != '\n') &&
(opp[i] != '\r') &&
(opp[i] != '\t')) ||
(opp[i] > '~'))
{
printable=0;
break;
}
}
if (printable)
/* printable string */
{
if (BIO_puts(bp, ":") <= 0)
goto end;
if (BIO_write(bp,(const char *)opp,
os->length) <= 0)
goto end;
}
else if (!dump)
/* not printable => print octet string
* as hex dump */
{
if (BIO_puts(bp, "[HEX DUMP]:") <= 0)
goto end;
for (i=0; i<os->length; i++)
{
if (BIO_printf(bp,"%02X"
, opp[i]) <= 0)
goto end;
}
}
else
/* print the normal dump */
{
if (!nl)
{
if (BIO_puts(bp, "\n") <= 0)
goto end;
}
if (!BIO_hexdump(bp, opp,
((dump == -1 || dump >
os->length)?os->length:dump),
dump_indent))
goto end;
nl=1;
}
}
if (os != NULL)
{
M_ASN1_OCTET_STRING_free(os);
os=NULL;
}
}
else if (tag == V_ASN1_INTEGER)
{
ASN1_INTEGER *bs;
int i;
opp=op;
bs=d2i_ASN1_INTEGER(NULL,&opp,len+hl);
if (bs != NULL)
{
if (BIO_puts(bp, ":") <= 0) goto end;
if (bs->type == V_ASN1_NEG_INTEGER)
if (BIO_puts(bp, "-") <= 0)
goto end;
for (i=0; i<bs->length; i++)
{
if (BIO_printf(bp,"%02X",
bs->data[i]) <= 0)
goto end;
}
if (bs->length == 0)
{
if (BIO_puts(bp, "00") <= 0)
goto end;
}
}
else
{
if (BIO_puts(bp, "BAD INTEGER") <= 0)
goto end;
}
M_ASN1_INTEGER_free(bs);
}
else if (tag == V_ASN1_ENUMERATED)
{
ASN1_ENUMERATED *bs;
int i;
opp=op;
bs=d2i_ASN1_ENUMERATED(NULL,&opp,len+hl);
if (bs != NULL)
{
if (BIO_puts(bp, ":") <= 0) goto end;
if (bs->type == V_ASN1_NEG_ENUMERATED)
if (BIO_puts(bp, "-") <= 0)
goto end;
for (i=0; i<bs->length; i++)
{
if (BIO_printf(bp,"%02X",
bs->data[i]) <= 0)
goto end;
}
if (bs->length == 0)
{
if (BIO_puts(bp, "00") <= 0)
goto end;
}
}
else
{
if (BIO_puts(bp, "BAD ENUMERATED") <= 0)
goto end;
}
M_ASN1_ENUMERATED_free(bs);
}
else if (len > 0 && dump)
{
if (!nl)
{
if (BIO_puts(bp, "\n") <= 0)
goto end;
}
if (!BIO_hexdump(bp,p,
((dump == -1 || dump > len)?len:dump),
dump_indent))
goto end;
nl=1;
}
if (!nl)
{
if (BIO_puts(bp, "\n") <= 0) goto end;
}
p+=len;
if ((tag == V_ASN1_EOC) && (xclass == 0))
{
ret=2; /* End of sequence */
goto end;
}
}
length-=len;
}
ret=1;
end:
if (o != NULL) ASN1_OBJECT_free(o);
if (os != NULL) M_ASN1_OCTET_STRING_free(os);
*pp=p;
return(ret);
}
const char *ASN1_tag2str(int tag)
{
static const char * const tag2str[] = {
"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
"NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
"VIDEOTEXSTRING", "IA5STRING", "UTCTIME","GENERALIZEDTIME", /* 21-24 */
"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
};
if((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
tag &= ~0x100;
if(tag < 0 || tag > 30) return "(unknown)";
return tag2str[tag];
}

View File

@ -0,0 +1,104 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
/* ASN1_ITEM versions of the above */
ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
{
ASN1_STRING *octmp;
if (!oct || !*oct) {
if (!(octmp = ASN1_STRING_new ())) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (oct) *oct = octmp;
} else octmp = *oct;
if(octmp->data) {
OPENSSL_free(octmp->data);
octmp->data = NULL;
}
if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR);
return NULL;
}
if (!octmp->data) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
return octmp;
}
/* Extract an ASN1 object from an ASN1_STRING */
void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it)
{
const unsigned char *p;
void *ret;
p = oct->data;
if(!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
return ret;
}

View File

@ -0,0 +1,496 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <assert.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/mem.h>
/* Must be large enough for biggest tag+length */
#define DEFAULT_ASN1_BUF_SIZE 20
typedef enum
{
ASN1_STATE_START,
ASN1_STATE_PRE_COPY,
ASN1_STATE_HEADER,
ASN1_STATE_HEADER_COPY,
ASN1_STATE_DATA_COPY,
ASN1_STATE_POST_COPY,
ASN1_STATE_DONE
} asn1_bio_state_t;
typedef struct BIO_ASN1_EX_FUNCS_st
{
asn1_ps_func *ex_func;
asn1_ps_func *ex_free_func;
} BIO_ASN1_EX_FUNCS;
typedef struct BIO_ASN1_BUF_CTX_t
{
/* Internal state */
asn1_bio_state_t state;
/* Internal buffer */
unsigned char *buf;
/* Size of buffer */
int bufsize;
/* Current position in buffer */
int bufpos;
/* Current buffer length */
int buflen;
/* Amount of data to copy */
int copylen;
/* Class and tag to use */
int asn1_class, asn1_tag;
asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
/* Extra buffer for prefix and suffix data */
unsigned char *ex_buf;
int ex_len;
int ex_pos;
void *ex_arg;
} BIO_ASN1_BUF_CTX;
static int asn1_bio_write(BIO *h, const char *buf,int num);
static int asn1_bio_read(BIO *h, char *buf, int size);
static int asn1_bio_puts(BIO *h, const char *str);
static int asn1_bio_gets(BIO *h, char *str, int size);
static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int asn1_bio_new(BIO *h);
static int asn1_bio_free(BIO *data);
static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb fp);
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
asn1_ps_func *cleanup, asn1_bio_state_t next);
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
asn1_ps_func *setup,
asn1_bio_state_t ex_state,
asn1_bio_state_t other_state);
static const BIO_METHOD methods_asn1=
{
BIO_TYPE_ASN1,
"asn1",
asn1_bio_write,
asn1_bio_read,
asn1_bio_puts,
asn1_bio_gets,
asn1_bio_ctrl,
asn1_bio_new,
asn1_bio_free,
asn1_bio_callback_ctrl,
};
const BIO_METHOD *BIO_f_asn1(void)
{
return(&methods_asn1);
}
static int asn1_bio_new(BIO *b)
{
BIO_ASN1_BUF_CTX *ctx;
ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
if (!ctx)
return 0;
if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE))
{
OPENSSL_free(ctx);
return 0;
}
b->init = 1;
b->ptr = (char *)ctx;
b->flags = 0;
return 1;
}
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
{
ctx->buf = OPENSSL_malloc(size);
if (!ctx->buf)
return 0;
ctx->bufsize = size;
ctx->bufpos = 0;
ctx->buflen = 0;
ctx->copylen = 0;
ctx->asn1_class = V_ASN1_UNIVERSAL;
ctx->asn1_tag = V_ASN1_OCTET_STRING;
ctx->ex_buf = 0;
ctx->ex_pos = 0;
ctx->ex_len = 0;
ctx->state = ASN1_STATE_START;
return 1;
}
static int asn1_bio_free(BIO *b)
{
BIO_ASN1_BUF_CTX *ctx;
ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
if (ctx == NULL)
return 0;
if (ctx->buf)
OPENSSL_free(ctx->buf);
OPENSSL_free(ctx);
b->init = 0;
b->ptr = NULL;
b->flags = 0;
return 1;
}
static int asn1_bio_write(BIO *b, const char *in , int inl)
{
BIO_ASN1_BUF_CTX *ctx;
int wrmax, wrlen, ret;
unsigned char *p;
if (!in || (inl < 0) || (b->next_bio == NULL))
return 0;
ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
if (ctx == NULL)
return 0;
wrlen = 0;
ret = -1;
for(;;)
{
switch (ctx->state)
{
/* Setup prefix data, call it */
case ASN1_STATE_START:
if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
return 0;
break;
/* Copy any pre data first */
case ASN1_STATE_PRE_COPY:
ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
ASN1_STATE_HEADER);
if (ret <= 0)
goto done;
break;
case ASN1_STATE_HEADER:
ctx->buflen =
ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
assert(ctx->buflen <= ctx->bufsize);
p = ctx->buf;
ASN1_put_object(&p, 0, inl,
ctx->asn1_tag, ctx->asn1_class);
ctx->copylen = inl;
ctx->state = ASN1_STATE_HEADER_COPY;
break;
case ASN1_STATE_HEADER_COPY:
ret = BIO_write(b->next_bio,
ctx->buf + ctx->bufpos, ctx->buflen);
if (ret <= 0)
goto done;
ctx->buflen -= ret;
if (ctx->buflen)
ctx->bufpos += ret;
else
{
ctx->bufpos = 0;
ctx->state = ASN1_STATE_DATA_COPY;
}
break;
case ASN1_STATE_DATA_COPY:
if (inl > ctx->copylen)
wrmax = ctx->copylen;
else
wrmax = inl;
ret = BIO_write(b->next_bio, in, wrmax);
if (ret <= 0)
break;
wrlen += ret;
ctx->copylen -= ret;
in += ret;
inl -= ret;
if (ctx->copylen == 0)
ctx->state = ASN1_STATE_HEADER;
if (inl == 0)
goto done;
break;
default:
BIO_clear_retry_flags(b);
return 0;
}
}
done:
BIO_clear_retry_flags(b);
BIO_copy_next_retry(b);
return (wrlen > 0) ? wrlen : ret;
}
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
asn1_ps_func *cleanup, asn1_bio_state_t next)
{
int ret;
if (ctx->ex_len <= 0)
return 1;
for(;;)
{
ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos,
ctx->ex_len);
if (ret <= 0)
break;
ctx->ex_len -= ret;
if (ctx->ex_len > 0)
ctx->ex_pos += ret;
else
{
if(cleanup)
cleanup(b, &ctx->ex_buf, &ctx->ex_len,
&ctx->ex_arg);
ctx->state = next;
ctx->ex_pos = 0;
break;
}
}
return ret;
}
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
asn1_ps_func *setup,
asn1_bio_state_t ex_state,
asn1_bio_state_t other_state)
{
if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg))
{
BIO_clear_retry_flags(b);
return 0;
}
if (ctx->ex_len > 0)
ctx->state = ex_state;
else
ctx->state = other_state;
return 1;
}
static int asn1_bio_read(BIO *b, char *in , int inl)
{
if (!b->next_bio)
return 0;
return BIO_read(b->next_bio, in , inl);
}
static int asn1_bio_puts(BIO *b, const char *str)
{
return asn1_bio_write(b, str, strlen(str));
}
static int asn1_bio_gets(BIO *b, char *str, int size)
{
if (!b->next_bio)
return 0;
return BIO_gets(b->next_bio, str , size);
}
static long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb fp)
{
if (b->next_bio == NULL) return(0);
return BIO_callback_ctrl(b->next_bio,cmd,fp);
}
static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
{
BIO_ASN1_BUF_CTX *ctx;
BIO_ASN1_EX_FUNCS *ex_func;
long ret = 1;
ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
if (ctx == NULL)
return 0;
switch(cmd)
{
case BIO_C_SET_PREFIX:
ex_func = arg2;
ctx->prefix = ex_func->ex_func;
ctx->prefix_free = ex_func->ex_free_func;
break;
case BIO_C_GET_PREFIX:
ex_func = arg2;
ex_func->ex_func = ctx->prefix;
ex_func->ex_free_func = ctx->prefix_free;
break;
case BIO_C_SET_SUFFIX:
ex_func = arg2;
ctx->suffix = ex_func->ex_func;
ctx->suffix_free = ex_func->ex_free_func;
break;
case BIO_C_GET_SUFFIX:
ex_func = arg2;
ex_func->ex_func = ctx->suffix;
ex_func->ex_free_func = ctx->suffix_free;
break;
case BIO_C_SET_EX_ARG:
ctx->ex_arg = arg2;
break;
case BIO_C_GET_EX_ARG:
*(void **)arg2 = ctx->ex_arg;
break;
case BIO_CTRL_FLUSH:
if (!b->next_bio)
return 0;
/* Call post function if possible */
if (ctx->state == ASN1_STATE_HEADER)
{
if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
return 0;
}
if (ctx->state == ASN1_STATE_POST_COPY)
{
ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
ASN1_STATE_DONE);
if (ret <= 0)
return ret;
}
if (ctx->state == ASN1_STATE_DONE)
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
else
{
BIO_clear_retry_flags(b);
return 0;
}
break;
default:
if (!b->next_bio)
return 0;
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
}
return ret;
}
static int asn1_bio_set_ex(BIO *b, int cmd,
asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
{
BIO_ASN1_EX_FUNCS extmp;
extmp.ex_func = ex_func;
extmp.ex_free_func = ex_free_func;
return BIO_ctrl(b, cmd, 0, &extmp);
}
static int asn1_bio_get_ex(BIO *b, int cmd,
asn1_ps_func **ex_func, asn1_ps_func **ex_free_func)
{
BIO_ASN1_EX_FUNCS extmp;
int ret;
ret = BIO_ctrl(b, cmd, 0, &extmp);
if (ret > 0)
{
*ex_func = extmp.ex_func;
*ex_free_func = extmp.ex_free_func;
}
return ret;
}
int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free)
{
return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
}
int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free)
{
return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
}
int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free)
{
return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
}
int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free)
{
return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
}

View File

@ -0,0 +1,254 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <assert.h>
#include <openssl/asn1t.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/mem.h>
/* Experimental NDEF ASN1 BIO support routines */
/* The usage is quite simple, initialize an ASN1 structure,
* get a BIO from it then any data written through the BIO
* will end up translated to approptiate format on the fly.
* The data is streamed out and does *not* need to be
* all held in memory at once.
*
* When the BIO is flushed the output is finalized and any
* signatures etc written out.
*
* The BIO is a 'proper' BIO and can handle non blocking I/O
* correctly.
*
* The usage is simple. The implementation is *not*...
*/
/* BIO support data stored in the ASN1 BIO ex_arg */
typedef struct ndef_aux_st
{
/* ASN1 structure this BIO refers to */
ASN1_VALUE *val;
const ASN1_ITEM *it;
/* Top of the BIO chain */
BIO *ndef_bio;
/* Output BIO */
BIO *out;
/* Boundary where content is inserted */
unsigned char **boundary;
/* DER buffer start */
unsigned char *derbuf;
} NDEF_SUPPORT;
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
{
NDEF_SUPPORT *ndef_aux = NULL;
BIO *asn_bio = NULL;
const ASN1_AUX *aux = it->funcs;
ASN1_STREAM_ARG sarg;
if (!aux || !aux->asn1_cb)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
return NULL;
}
ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
asn_bio = BIO_new(BIO_f_asn1());
/* ASN1 bio needs to be next to output BIO */
out = BIO_push(asn_bio, out);
if (!ndef_aux || !asn_bio || !out)
goto err;
BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
/* Now let callback prepend any digest, cipher etc BIOs
* ASN1 structure needs.
*/
sarg.out = out;
sarg.ndef_bio = NULL;
sarg.boundary = NULL;
if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
goto err;
ndef_aux->val = val;
ndef_aux->it = it;
ndef_aux->ndef_bio = sarg.ndef_bio;
ndef_aux->boundary = sarg.boundary;
ndef_aux->out = out;
BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
return sarg.ndef_bio;
err:
if (asn_bio)
BIO_free(asn_bio);
if (ndef_aux)
OPENSSL_free(ndef_aux);
return NULL;
}
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
{
NDEF_SUPPORT *ndef_aux;
unsigned char *p;
int derlen;
if (!parg)
return 0;
ndef_aux = *(NDEF_SUPPORT **)parg;
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
p = OPENSSL_malloc(derlen);
if (p == NULL)
return 0;
ndef_aux->derbuf = p;
*pbuf = p;
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
if (!*ndef_aux->boundary)
return 0;
*plen = *ndef_aux->boundary - *pbuf;
return 1;
}
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
{
NDEF_SUPPORT *ndef_aux;
if (!parg)
return 0;
ndef_aux = *(NDEF_SUPPORT **)parg;
if (ndef_aux->derbuf)
OPENSSL_free(ndef_aux->derbuf);
ndef_aux->derbuf = NULL;
*pbuf = NULL;
*plen = 0;
return 1;
}
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
{
NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
if (!ndef_prefix_free(b, pbuf, plen, parg))
return 0;
OPENSSL_free(*pndef_aux);
*pndef_aux = NULL;
return 1;
}
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
{
NDEF_SUPPORT *ndef_aux;
unsigned char *p;
int derlen;
const ASN1_AUX *aux;
ASN1_STREAM_ARG sarg;
if (!parg)
return 0;
ndef_aux = *(NDEF_SUPPORT **)parg;
aux = ndef_aux->it->funcs;
/* Finalize structures */
sarg.ndef_bio = ndef_aux->ndef_bio;
sarg.out = ndef_aux->out;
sarg.boundary = ndef_aux->boundary;
if (aux->asn1_cb(ASN1_OP_STREAM_POST,
&ndef_aux->val, ndef_aux->it, &sarg) <= 0)
return 0;
derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
p = OPENSSL_malloc(derlen);
if (p == NULL)
return 0;
ndef_aux->derbuf = p;
*pbuf = p;
derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
if (!*ndef_aux->boundary)
return 0;
*pbuf = *ndef_aux->boundary;
*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
return 1;
}

View File

@ -0,0 +1,135 @@
#!/usr/local/bin/perl -w
# Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
# 2000.
#
# ====================================================================
# Copyright (c) 2000 The OpenSSL Project. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# 3. All advertising materials mentioning features or use of this
# software must display the following acknowledgment:
# "This product includes software developed by the OpenSSL Project
# for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
#
# 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
# endorse or promote products derived from this software without
# prior written permission. For written permission, please contact
# licensing@OpenSSL.org.
#
# 5. Products derived from this software may not be called "OpenSSL"
# nor may "OpenSSL" appear in their names without prior written
# permission of the OpenSSL Project.
#
# 6. Redistributions of any form whatsoever must retain the following
# acknowledgment:
# "This product includes software developed by the OpenSSL Project
# for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
#
# THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
# OF THE POSSIBILITY OF SUCH DAMAGE.
# ====================================================================
#
# This product includes cryptographic software written by Eric Young
# (eay@cryptsoft.com). This product includes software written by Tim
# Hudson (tjh@cryptsoft.com).
use strict;
my ($i, @arr);
# Set up an array with the type of ASCII characters
# Each set bit represents a character property.
# RFC2253 character properties
my $RFC2253_ESC = 1; # Character escaped with \
my $ESC_CTRL = 2; # Escaped control character
# These are used with RFC1779 quoting using "
my $NOESC_QUOTE = 8; # Not escaped if quoted
my $PSTRING_CHAR = 0x10; # Valid PrintableString character
my $RFC2253_FIRST_ESC = 0x20; # Escaped with \ if first character
my $RFC2253_LAST_ESC = 0x40; # Escaped with \ if last character
for($i = 0; $i < 128; $i++) {
# Set the RFC2253 escape characters (control)
$arr[$i] = 0;
if(($i < 32) || ($i > 126)) {
$arr[$i] |= $ESC_CTRL;
}
# Some PrintableString characters
if( ( ( $i >= ord("a")) && ( $i <= ord("z")) )
|| ( ( $i >= ord("A")) && ( $i <= ord("Z")) )
|| ( ( $i >= ord("0")) && ( $i <= ord("9")) ) ) {
$arr[$i] |= $PSTRING_CHAR;
}
}
# Now setup the rest
# Remaining RFC2253 escaped characters
$arr[ord(" ")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC | $RFC2253_LAST_ESC;
$arr[ord("#")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC;
$arr[ord(",")] |= $NOESC_QUOTE | $RFC2253_ESC;
$arr[ord("+")] |= $NOESC_QUOTE | $RFC2253_ESC;
$arr[ord("\"")] |= $RFC2253_ESC;
$arr[ord("\\")] |= $RFC2253_ESC;
$arr[ord("<")] |= $NOESC_QUOTE | $RFC2253_ESC;
$arr[ord(">")] |= $NOESC_QUOTE | $RFC2253_ESC;
$arr[ord(";")] |= $NOESC_QUOTE | $RFC2253_ESC;
# Remaining PrintableString characters
$arr[ord(" ")] |= $PSTRING_CHAR;
$arr[ord("'")] |= $PSTRING_CHAR;
$arr[ord("(")] |= $PSTRING_CHAR;
$arr[ord(")")] |= $PSTRING_CHAR;
$arr[ord("+")] |= $PSTRING_CHAR;
$arr[ord(",")] |= $PSTRING_CHAR;
$arr[ord("-")] |= $PSTRING_CHAR;
$arr[ord(".")] |= $PSTRING_CHAR;
$arr[ord("/")] |= $PSTRING_CHAR;
$arr[ord(":")] |= $PSTRING_CHAR;
$arr[ord("=")] |= $PSTRING_CHAR;
$arr[ord("?")] |= $PSTRING_CHAR;
# Now generate the C code
print <<EOF;
/* Auto generated with chartype.pl script.
* Mask of various character properties
*/
static const unsigned char char_type[] = {
EOF
for($i = 0; $i < 128; $i++) {
print("\n") if($i && (($i % 16) == 0));
printf("%2d", $arr[$i]);
print(",") if ($i != 127);
}
print("\n};\n\n");

View File

@ -0,0 +1,206 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
/* Based on a_int.c: equivalent ENUMERATED functions */
int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a)
{
int i,n=0;
static const char *h="0123456789ABCDEF";
char buf[2];
if (a == NULL) return(0);
if (a->length == 0)
{
if (BIO_write(bp,"00",2) != 2) goto err;
n=2;
}
else
{
for (i=0; i<a->length; i++)
{
if ((i != 0) && (i%35 == 0))
{
if (BIO_write(bp,"\\\n",2) != 2) goto err;
n+=2;
}
buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f];
buf[1]=h[((unsigned char)a->data[i] )&0x0f];
if (BIO_write(bp,buf,2) != 2) goto err;
n+=2;
}
}
return(n);
err:
return(-1);
}
int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
{
int ret=0;
int i,j,k,m,n,again,bufsize;
unsigned char *s=NULL,*sp;
unsigned char *bufp;
int num=0,slen=0,first=1;
bs->type=V_ASN1_ENUMERATED;
bufsize=BIO_gets(bp,buf,size);
for (;;)
{
if (bufsize < 1) goto err_sl;
i=bufsize;
if (buf[i-1] == '\n') buf[--i]='\0';
if (i == 0) goto err_sl;
if (buf[i-1] == '\r') buf[--i]='\0';
if (i == 0) goto err_sl;
again=(buf[i-1] == '\\');
for (j=0; j<i; j++)
{
if (!( ((buf[j] >= '0') && (buf[j] <= '9')) ||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
((buf[j] >= 'A') && (buf[j] <= 'F'))))
{
i=j;
break;
}
}
buf[i]='\0';
/* We have now cleared all the crap off the end of the
* line */
if (i < 2) goto err_sl;
bufp=(unsigned char *)buf;
if (first)
{
first=0;
if ((bufp[0] == '0') && (buf[1] == '0'))
{
bufp+=2;
i-=2;
}
}
k=0;
i-=again;
if (i%2 != 0)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
goto err;
}
i/=2;
if (num+i > slen)
{
if (s == NULL)
sp=(unsigned char *)OPENSSL_malloc(
(unsigned int)num+i*2);
else
sp=(unsigned char *)OPENSSL_realloc(s,
(unsigned int)num+i*2);
if (sp == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
s=sp;
slen=num+i*2;
}
for (j=0; j<i; j++,k+=2)
{
for (n=0; n<2; n++)
{
m=bufp[k+n];
if ((m >= '0') && (m <= '9'))
m-='0';
else if ((m >= 'a') && (m <= 'f'))
m=m-'a'+10;
else if ((m >= 'A') && (m <= 'F'))
m=m-'A'+10;
else
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
goto err;
}
s[num+j]<<=4;
s[num+j]|=m;
}
}
num+=i;
if (again)
bufsize=BIO_gets(bp,buf,size);
else
break;
}
bs->length=num;
bs->data=s;
ret=1;
err:
if (0)
{
err_sl:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
}
if (s != NULL)
OPENSSL_free(s);
return(ret);
}

View File

@ -0,0 +1,210 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a)
{
int i,n=0;
static const char *h="0123456789ABCDEF";
char buf[2];
if (a == NULL) return(0);
if (a->type & V_ASN1_NEG)
{
if (BIO_write(bp, "-", 1) != 1) goto err;
n = 1;
}
if (a->length == 0)
{
if (BIO_write(bp,"00",2) != 2) goto err;
n += 2;
}
else
{
for (i=0; i<a->length; i++)
{
if ((i != 0) && (i%35 == 0))
{
if (BIO_write(bp,"\\\n",2) != 2) goto err;
n+=2;
}
buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f];
buf[1]=h[((unsigned char)a->data[i] )&0x0f];
if (BIO_write(bp,buf,2) != 2) goto err;
n+=2;
}
}
return(n);
err:
return(-1);
}
int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
{
int ret=0;
int i,j,k,m,n,again,bufsize;
unsigned char *s=NULL,*sp;
unsigned char *bufp;
int num=0,slen=0,first=1;
bs->type=V_ASN1_INTEGER;
bufsize=BIO_gets(bp,buf,size);
for (;;)
{
if (bufsize < 1) goto err_sl;
i=bufsize;
if (buf[i-1] == '\n') buf[--i]='\0';
if (i == 0) goto err_sl;
if (buf[i-1] == '\r') buf[--i]='\0';
if (i == 0) goto err_sl;
again=(buf[i-1] == '\\');
for (j=0; j<i; j++)
{
if (!( ((buf[j] >= '0') && (buf[j] <= '9')) ||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
((buf[j] >= 'A') && (buf[j] <= 'F'))))
{
i=j;
break;
}
}
buf[i]='\0';
/* We have now cleared all the crap off the end of the
* line */
if (i < 2) goto err_sl;
bufp=(unsigned char *)buf;
if (first)
{
first=0;
if ((bufp[0] == '0') && (buf[1] == '0'))
{
bufp+=2;
i-=2;
}
}
k=0;
i-=again;
if (i%2 != 0)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
goto err;
}
i/=2;
if (num+i > slen)
{
if (s == NULL)
sp=(unsigned char *)OPENSSL_malloc(
(unsigned int)num+i*2);
else
sp=OPENSSL_realloc_clean(s,slen,num+i*2);
if (sp == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
s=sp;
slen=num+i*2;
}
for (j=0; j<i; j++,k+=2)
{
for (n=0; n<2; n++)
{
m=bufp[k+n];
if ((m >= '0') && (m <= '9'))
m-='0';
else if ((m >= 'a') && (m <= 'f'))
m=m-'a'+10;
else if ((m >= 'A') && (m <= 'F'))
m=m-'A'+10;
else
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
goto err;
}
s[num+j]<<=4;
s[num+j]|=m;
}
}
num+=i;
if (again)
bufsize=BIO_gets(bp,buf,size);
else
break;
}
bs->length=num;
bs->data=s;
ret=1;
err:
if (0)
{
err_sl:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
}
if (s != NULL)
OPENSSL_free(s);
return(ret);
}

View File

@ -0,0 +1,204 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/mem.h>
int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type)
{
int i,n=0;
static const char *h="0123456789ABCDEF";
char buf[2];
if (a == NULL) return(0);
if (a->length == 0)
{
if (BIO_write(bp,"0",1) != 1) goto err;
n=1;
}
else
{
for (i=0; i<a->length; i++)
{
if ((i != 0) && (i%35 == 0))
{
if (BIO_write(bp,"\\\n",2) != 2) goto err;
n+=2;
}
buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f];
buf[1]=h[((unsigned char)a->data[i] )&0x0f];
if (BIO_write(bp,buf,2) != 2) goto err;
n+=2;
}
}
return(n);
err:
return(-1);
}
int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
{
int ret=0;
int i,j,k,m,n,again,bufsize;
unsigned char *s=NULL,*sp;
unsigned char *bufp;
int num=0,slen=0,first=1;
bufsize=BIO_gets(bp,buf,size);
for (;;)
{
if (bufsize < 1)
{
if (first)
break;
else
goto err_sl;
}
first=0;
i=bufsize;
if (buf[i-1] == '\n') buf[--i]='\0';
if (i == 0) goto err_sl;
if (buf[i-1] == '\r') buf[--i]='\0';
if (i == 0) goto err_sl;
again=(buf[i-1] == '\\');
for (j=i-1; j>0; j--)
{
if (!( ((buf[j] >= '0') && (buf[j] <= '9')) ||
((buf[j] >= 'a') && (buf[j] <= 'f')) ||
((buf[j] >= 'A') && (buf[j] <= 'F'))))
{
i=j;
break;
}
}
buf[i]='\0';
/* We have now cleared all the crap off the end of the
* line */
if (i < 2) goto err_sl;
bufp=(unsigned char *)buf;
k=0;
i-=again;
if (i%2 != 0)
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
goto err;
}
i/=2;
if (num+i > slen)
{
if (s == NULL)
sp=(unsigned char *)OPENSSL_malloc(
(unsigned int)num+i*2);
else
sp=(unsigned char *)OPENSSL_realloc(s,
(unsigned int)num+i*2);
if (sp == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
goto err;
}
s=sp;
slen=num+i*2;
}
for (j=0; j<i; j++,k+=2)
{
for (n=0; n<2; n++)
{
m=bufp[k+n];
if ((m >= '0') && (m <= '9'))
m-='0';
else if ((m >= 'a') && (m <= 'f'))
m=m-'a'+10;
else if ((m >= 'A') && (m <= 'F'))
m=m-'A'+10;
else
{
OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
goto err;
}
s[num+j]<<=4;
s[num+j]|=m;
}
}
num+=i;
if (again)
bufsize=BIO_gets(bp,buf,size);
else
break;
}
bs->length=num;
bs->data=s;
ret=1;
err:
if (0)
{
err_sl:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
}
if (s != NULL)
OPENSSL_free(s);
return(ret);
}

View File

@ -0,0 +1,102 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/mem.h>
int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
BIT_STRING_BITNAME *tbl, int indent)
{
BIT_STRING_BITNAME *bnam;
char first = 1;
BIO_printf(out, "%*s", indent, "");
for(bnam = tbl; bnam->lname; bnam++) {
if(ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
if(!first) BIO_puts(out, ", ");
BIO_puts(out, bnam->lname);
first = 0;
}
}
BIO_puts(out, "\n");
return 1;
}
int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value,
BIT_STRING_BITNAME *tbl)
{
int bitnum;
bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
if(bitnum < 0) return 0;
if(bs) {
if(!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
return 0;
}
return 1;
}
int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl)
{
BIT_STRING_BITNAME *bnam;
for(bnam = tbl; bnam->lname; bnam++) {
if(!strcmp(bnam->sname, name) ||
!strcmp(bnam->lname, name) ) return bnam->bitnum;
}
return -1;
}

View File

@ -0,0 +1,112 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/mem.h>
int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
unsigned char *buf, int off)
{
int n,i;
const char *neg;
if (num == NULL) return(1);
neg = (BN_is_negative(num))?"-":"";
if(!BIO_indent(bp,off,128))
return 0;
if (BN_is_zero(num))
{
if (BIO_printf(bp, "%s 0\n", number) <= 0)
return 0;
return 1;
}
if (BN_num_bytes(num) <= sizeof(long))
{
if (BIO_printf(bp,"%s %s%lu (%s0x%lx)\n",number,neg,
(unsigned long)num->d[0],neg,(unsigned long)num->d[0])
<= 0) return(0);
}
else
{
buf[0]=0;
if (BIO_printf(bp,"%s%s",number,
(neg[0] == '-')?" (Negative)":"") <= 0)
return(0);
n=BN_bn2bin(num,&buf[1]);
if (buf[1] & 0x80)
n++;
else buf++;
for (i=0; i<n; i++)
{
if ((i%15) == 0)
{
if(BIO_puts(bp,"\n") <= 0
|| !BIO_indent(bp,off+4,128))
return 0;
}
if (BIO_printf(bp,"%02x%s",buf[i],((i+1) == n)?"":":")
<= 0) return(0);
}
if (BIO_write(bp,"\n",1) <= 0) return(0);
}
return(1);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,695 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/mem.h>
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it,
int tag, int aclass);
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
int skcontlen, const ASN1_ITEM *item,
int do_sort, int iclass);
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt,
int tag, int aclass);
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it, int flags);
/* Top level i2d equivalents: the 'ndef' variant instructs the encoder
* to use indefinite length constructed encoding, where appropriate
*/
int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it)
{
return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
}
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
{
return asn1_item_flags_i2d(val, out, it, 0);
}
/* Encode an ASN1 item, this is use by the
* standard 'i2d' function. 'out' points to
* a buffer to output the data to.
*
* The new i2d has one additional feature. If the output
* buffer is NULL (i.e. *out == NULL) then a buffer is
* allocated and populated with the encoding.
*/
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it, int flags)
{
if (out && !*out)
{
unsigned char *p, *buf;
int len;
len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
if (len <= 0)
return len;
buf = OPENSSL_malloc(len);
if (!buf)
return -1;
p = buf;
ASN1_item_ex_i2d(&val, &p, it, -1, flags);
*out = buf;
return len;
}
return ASN1_item_ex_i2d(&val, out, it, -1, flags);
}
/* Encode an item, taking care of IMPLICIT tagging (if any).
* This function performs the normal item handling: it can be
* used in external types.
*/
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass)
{
const ASN1_TEMPLATE *tt = NULL;
unsigned char *p = NULL;
int i, seqcontlen, seqlen, ndef = 1;
const ASN1_COMPAT_FUNCS *cf;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb = 0;
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
return 0;
if (aux && aux->asn1_cb)
asn1_cb = aux->asn1_cb;
switch(it->itype)
{
case ASN1_ITYPE_PRIMITIVE:
if (it->templates)
return asn1_template_ex_i2d(pval, out, it->templates,
tag, aclass);
return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
break;
case ASN1_ITYPE_MSTRING:
return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
case ASN1_ITYPE_CHOICE:
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
return 0;
i = asn1_get_choice_selector(pval, it);
if ((i >= 0) && (i < it->tcount))
{
ASN1_VALUE **pchval;
const ASN1_TEMPLATE *chtt;
chtt = it->templates + i;
pchval = asn1_get_field_ptr(pval, chtt);
return asn1_template_ex_i2d(pchval, out, chtt,
-1, aclass);
}
/* Fixme: error condition if selector out of range */
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
return 0;
break;
case ASN1_ITYPE_EXTERN:
/* If new style i2d it does all the work */
ef = it->funcs;
return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
case ASN1_ITYPE_COMPAT:
/* old style hackery... */
cf = it->funcs;
if (out)
p = *out;
i = cf->asn1_i2d(*pval, out);
/* Fixup for IMPLICIT tag: note this messes up for tags > 30,
* but so did the old code. Tags > 30 are very rare anyway.
*/
if (out && (tag != -1))
*p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
return i;
case ASN1_ITYPE_NDEF_SEQUENCE:
/* Use indefinite length constructed if requested */
if (aclass & ASN1_TFLG_NDEF) ndef = 2;
/* fall through */
case ASN1_ITYPE_SEQUENCE:
i = asn1_enc_restore(&seqcontlen, out, pval, it);
/* An error occurred */
if (i < 0)
return 0;
/* We have a valid cached encoding... */
if (i > 0)
return seqcontlen;
/* Otherwise carry on */
seqcontlen = 0;
/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
if (tag == -1)
{
tag = V_ASN1_SEQUENCE;
/* Retain any other flags in aclass */
aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
| V_ASN1_UNIVERSAL;
}
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
return 0;
/* First work out sequence content length */
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
{
const ASN1_TEMPLATE *seqtt;
ASN1_VALUE **pseqval;
seqtt = asn1_do_adb(pval, tt, 1);
if (!seqtt)
return 0;
pseqval = asn1_get_field_ptr(pval, seqtt);
/* FIXME: check for errors in enhanced version */
seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
-1, aclass);
}
seqlen = ASN1_object_size(ndef, seqcontlen, tag);
if (!out)
return seqlen;
/* Output SEQUENCE header */
ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
{
const ASN1_TEMPLATE *seqtt;
ASN1_VALUE **pseqval;
seqtt = asn1_do_adb(pval, tt, 1);
if (!seqtt)
return 0;
pseqval = asn1_get_field_ptr(pval, seqtt);
/* FIXME: check for errors in enhanced version */
asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
}
if (ndef == 2)
ASN1_put_eoc(out);
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
return 0;
return seqlen;
default:
return 0;
}
return 0;
}
int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt)
{
return asn1_template_ex_i2d(pval, out, tt, -1, 0);
}
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt, int tag, int iclass)
{
int i, ret, flags, ttag, tclass, ndef;
size_t j;
flags = tt->flags;
/* Work out tag and class to use: tagging may come
* either from the template or the arguments, not both
* because this would create ambiguity. Additionally
* the iclass argument may contain some additional flags
* which should be noted and passed down to other levels.
*/
if (flags & ASN1_TFLG_TAG_MASK)
{
/* Error if argument and template tagging */
if (tag != -1)
/* FIXME: error code here */
return -1;
/* Get tagging from template */
ttag = tt->tag;
tclass = flags & ASN1_TFLG_TAG_CLASS;
}
else if (tag != -1)
{
/* No template tagging, get from arguments */
ttag = tag;
tclass = iclass & ASN1_TFLG_TAG_CLASS;
}
else
{
ttag = -1;
tclass = 0;
}
/*
* Remove any class mask from iflag.
*/
iclass &= ~ASN1_TFLG_TAG_CLASS;
/* At this point 'ttag' contains the outer tag to use,
* 'tclass' is the class and iclass is any flags passed
* to this function.
*/
/* if template and arguments require ndef, use it */
if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
ndef = 2;
else ndef = 1;
if (flags & ASN1_TFLG_SK_MASK)
{
/* SET OF, SEQUENCE OF */
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
int isset, sktag, skaclass;
int skcontlen, sklen;
ASN1_VALUE *skitem;
if (!*pval)
return 0;
if (flags & ASN1_TFLG_SET_OF)
{
isset = 1;
/* 2 means we reorder */
if (flags & ASN1_TFLG_SEQUENCE_OF)
isset = 2;
}
else isset = 0;
/* Work out inner tag value: if EXPLICIT
* or no tagging use underlying type.
*/
if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG))
{
sktag = ttag;
skaclass = tclass;
}
else
{
skaclass = V_ASN1_UNIVERSAL;
if (isset)
sktag = V_ASN1_SET;
else sktag = V_ASN1_SEQUENCE;
}
/* Determine total length of items */
skcontlen = 0;
for (j = 0; j < sk_ASN1_VALUE_num(sk); j++)
{
skitem = sk_ASN1_VALUE_value(sk, j);
skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
ASN1_ITEM_ptr(tt->item),
-1, iclass);
}
sklen = ASN1_object_size(ndef, skcontlen, sktag);
/* If EXPLICIT need length of surrounding tag */
if (flags & ASN1_TFLG_EXPTAG)
ret = ASN1_object_size(ndef, sklen, ttag);
else ret = sklen;
if (!out)
return ret;
/* Now encode this lot... */
/* EXPLICIT tag */
if (flags & ASN1_TFLG_EXPTAG)
ASN1_put_object(out, ndef, sklen, ttag, tclass);
/* SET or SEQUENCE and IMPLICIT tag */
ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
/* And the stuff itself */
asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
isset, iclass);
if (ndef == 2)
{
ASN1_put_eoc(out);
if (flags & ASN1_TFLG_EXPTAG)
ASN1_put_eoc(out);
}
return ret;
}
if (flags & ASN1_TFLG_EXPTAG)
{
/* EXPLICIT tagging */
/* Find length of tagged item */
i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item),
-1, iclass);
if (!i)
return 0;
/* Find length of EXPLICIT tag */
ret = ASN1_object_size(ndef, i, ttag);
if (out)
{
/* Output tag and item */
ASN1_put_object(out, ndef, i, ttag, tclass);
ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
-1, iclass);
if (ndef == 2)
ASN1_put_eoc(out);
}
return ret;
}
/* Either normal or IMPLICIT tagging: combine class and flags */
return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
ttag, tclass | iclass);
}
/* Temporary structure used to hold DER encoding of items for SET OF */
typedef struct {
unsigned char *data;
int length;
ASN1_VALUE *field;
} DER_ENC;
static int der_cmp(const void *a, const void *b)
{
const DER_ENC *d1 = a, *d2 = b;
int cmplen, i;
cmplen = (d1->length < d2->length) ? d1->length : d2->length;
i = memcmp(d1->data, d2->data, cmplen);
if (i)
return i;
return d1->length - d2->length;
}
/* Output the content octets of SET OF or SEQUENCE OF */
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
int skcontlen, const ASN1_ITEM *item,
int do_sort, int iclass)
{
size_t i;
ASN1_VALUE *skitem;
unsigned char *tmpdat = NULL, *p = NULL;
DER_ENC *derlst = NULL, *tder;
if (do_sort)
{
/* Don't need to sort less than 2 items */
if (sk_ASN1_VALUE_num(sk) < 2)
do_sort = 0;
else
{
derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
* sizeof(*derlst));
if (!derlst)
return 0;
tmpdat = OPENSSL_malloc(skcontlen);
if (!tmpdat)
{
OPENSSL_free(derlst);
return 0;
}
}
}
/* If not sorting just output each item */
if (!do_sort)
{
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
{
skitem = sk_ASN1_VALUE_value(sk, i);
ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
}
return 1;
}
p = tmpdat;
/* Doing sort: build up a list of each member's DER encoding */
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
{
skitem = sk_ASN1_VALUE_value(sk, i);
tder->data = p;
tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
tder->field = skitem;
}
/* Now sort them */
qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
/* Output sorted DER encoding */
p = *out;
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
{
memcpy(p, tder->data, tder->length);
p += tder->length;
}
*out = p;
/* If do_sort is 2 then reorder the STACK */
if (do_sort == 2)
{
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk);
i++, tder++)
(void)sk_ASN1_VALUE_set(sk, i, tder->field);
}
OPENSSL_free(derlst);
OPENSSL_free(tmpdat);
return 1;
}
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass)
{
int len;
int utype;
int usetag;
int ndef = 0;
utype = it->utype;
/* Get length of content octets and maybe find
* out the underlying type.
*/
len = asn1_ex_i2c(pval, NULL, &utype, it);
/* If SEQUENCE, SET or OTHER then header is
* included in pseudo content octets so don't
* include tag+length. We need to check here
* because the call to asn1_ex_i2c() could change
* utype.
*/
if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
(utype == V_ASN1_OTHER))
usetag = 0;
else usetag = 1;
/* -1 means omit type */
if (len == -1)
return 0;
/* -2 return is special meaning use ndef */
if (len == -2)
{
ndef = 2;
len = 0;
}
/* If not implicitly tagged get tag from underlying type */
if (tag == -1) tag = utype;
/* Output tag+length followed by content octets */
if (out)
{
if (usetag)
ASN1_put_object(out, ndef, len, tag, aclass);
asn1_ex_i2c(pval, *out, &utype, it);
if (ndef)
ASN1_put_eoc(out);
else
*out += len;
}
if (usetag)
return ASN1_object_size(ndef, len, tag);
return len;
}
/* Produce content octets from a structure */
int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
const ASN1_ITEM *it)
{
ASN1_BOOLEAN *tbool = NULL;
ASN1_STRING *strtmp;
ASN1_OBJECT *otmp;
int utype;
const unsigned char *cont;
unsigned char c;
int len;
const ASN1_PRIMITIVE_FUNCS *pf;
pf = it->funcs;
if (pf && pf->prim_i2c)
return pf->prim_i2c(pval, cout, putype, it);
/* Should type be omitted? */
if ((it->itype != ASN1_ITYPE_PRIMITIVE)
|| (it->utype != V_ASN1_BOOLEAN))
{
if (!*pval) return -1;
}
if (it->itype == ASN1_ITYPE_MSTRING)
{
/* If MSTRING type set the underlying type */
strtmp = (ASN1_STRING *)*pval;
utype = strtmp->type;
*putype = utype;
}
else if (it->utype == V_ASN1_ANY)
{
/* If ANY set type and pointer to value */
ASN1_TYPE *typ;
typ = (ASN1_TYPE *)*pval;
utype = typ->type;
*putype = utype;
pval = &typ->value.asn1_value;
}
else utype = *putype;
switch(utype)
{
case V_ASN1_OBJECT:
otmp = (ASN1_OBJECT *)*pval;
cont = otmp->data;
len = otmp->length;
break;
case V_ASN1_NULL:
cont = NULL;
len = 0;
break;
case V_ASN1_BOOLEAN:
tbool = (ASN1_BOOLEAN *)pval;
if (*tbool == -1)
return -1;
if (it->utype != V_ASN1_ANY)
{
/* Default handling if value == size field then omit */
if (*tbool && (it->size > 0))
return -1;
if (!*tbool && !it->size)
return -1;
}
c = (unsigned char)*tbool;
cont = &c;
len = 1;
break;
case V_ASN1_BIT_STRING:
return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
cout ? &cout : NULL);
break;
case V_ASN1_INTEGER:
case V_ASN1_NEG_INTEGER:
case V_ASN1_ENUMERATED:
case V_ASN1_NEG_ENUMERATED:
/* These are all have the same content format
* as ASN1_INTEGER
*/
return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval,
cout ? &cout : NULL);
break;
case V_ASN1_OCTET_STRING:
case V_ASN1_NUMERICSTRING:
case V_ASN1_PRINTABLESTRING:
case V_ASN1_T61STRING:
case V_ASN1_VIDEOTEXSTRING:
case V_ASN1_IA5STRING:
case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME:
case V_ASN1_GRAPHICSTRING:
case V_ASN1_VISIBLESTRING:
case V_ASN1_GENERALSTRING:
case V_ASN1_UNIVERSALSTRING:
case V_ASN1_BMPSTRING:
case V_ASN1_UTF8STRING:
case V_ASN1_SEQUENCE:
case V_ASN1_SET:
default:
/* All based on ASN1_STRING and handled the same */
strtmp = (ASN1_STRING *)*pval;
/* Special handling for NDEF */
if ((it->size == ASN1_TFLG_NDEF)
&& (strtmp->flags & ASN1_STRING_FLAG_NDEF))
{
if (cout)
{
strtmp->data = cout;
strtmp->length = 0;
}
/* Special return code */
return -2;
}
cont = strtmp->data;
len = strtmp->length;
break;
}
if (cout && len)
memcpy(cout, cont, len);
return len;
}

View File

@ -0,0 +1,264 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/mem.h>
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine);
/* Free up an ASN1 structure */
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
{
asn1_item_combine_free(&val, it, 0);
}
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
asn1_item_combine_free(pval, it, 0);
}
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
{
const ASN1_TEMPLATE *tt = NULL, *seqtt;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_COMPAT_FUNCS *cf;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb;
int i;
if (!pval)
return;
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
return;
if (aux && aux->asn1_cb)
asn1_cb = aux->asn1_cb;
else
asn1_cb = 0;
switch(it->itype)
{
case ASN1_ITYPE_PRIMITIVE:
if (it->templates)
ASN1_template_free(pval, it->templates);
else
ASN1_primitive_free(pval, it);
break;
case ASN1_ITYPE_MSTRING:
ASN1_primitive_free(pval, it);
break;
case ASN1_ITYPE_CHOICE:
if (asn1_cb)
{
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
if (i == 2)
return;
}
i = asn1_get_choice_selector(pval, it);
if ((i >= 0) && (i < it->tcount))
{
ASN1_VALUE **pchval;
tt = it->templates + i;
pchval = asn1_get_field_ptr(pval, tt);
ASN1_template_free(pchval, tt);
}
if (asn1_cb)
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
if (!combine)
{
OPENSSL_free(*pval);
*pval = NULL;
}
break;
case ASN1_ITYPE_COMPAT:
cf = it->funcs;
if (cf && cf->asn1_free)
cf->asn1_free(*pval);
break;
case ASN1_ITYPE_EXTERN:
ef = it->funcs;
if (ef && ef->asn1_ex_free)
ef->asn1_ex_free(pval, it);
break;
case ASN1_ITYPE_NDEF_SEQUENCE:
case ASN1_ITYPE_SEQUENCE:
if (!asn1_refcount_dec_and_test_zero(pval, it))
return;
if (asn1_cb)
{
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
if (i == 2)
return;
}
asn1_enc_free(pval, it);
/* If we free up as normal we will invalidate any
* ANY DEFINED BY field and we wont be able to
* determine the type of the field it defines. So
* free up in reverse order.
*/
tt = it->templates + it->tcount - 1;
for (i = 0; i < it->tcount; tt--, i++)
{
ASN1_VALUE **pseqval;
seqtt = asn1_do_adb(pval, tt, 0);
if (!seqtt)
continue;
pseqval = asn1_get_field_ptr(pval, seqtt);
ASN1_template_free(pseqval, seqtt);
}
if (asn1_cb)
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
if (!combine)
{
OPENSSL_free(*pval);
*pval = NULL;
}
break;
}
}
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
size_t i;
if (tt->flags & ASN1_TFLG_SK_MASK)
{
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
{
ASN1_VALUE *vtmp;
vtmp = sk_ASN1_VALUE_value(sk, i);
asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item),
0);
}
sk_ASN1_VALUE_free(sk);
*pval = NULL;
}
else
asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
tt->flags & ASN1_TFLG_COMBINE);
}
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
int utype;
if (it)
{
const ASN1_PRIMITIVE_FUNCS *pf;
pf = it->funcs;
if (pf && pf->prim_free)
{
pf->prim_free(pval, it);
return;
}
}
/* Special case: if 'it' is NULL free contents of ASN1_TYPE */
if (!it)
{
ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
utype = typ->type;
pval = &typ->value.asn1_value;
if (!*pval)
return;
}
else if (it->itype == ASN1_ITYPE_MSTRING)
{
utype = -1;
if (!*pval)
return;
}
else
{
utype = it->utype;
if ((utype != V_ASN1_BOOLEAN) && !*pval)
return;
}
switch(utype)
{
case V_ASN1_OBJECT:
ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
break;
case V_ASN1_BOOLEAN:
if (it)
*(ASN1_BOOLEAN *)pval = it->size;
else
*(ASN1_BOOLEAN *)pval = -1;
return;
case V_ASN1_NULL:
break;
case V_ASN1_ANY:
ASN1_primitive_free(pval, NULL);
OPENSSL_free(*pval);
break;
default:
ASN1_STRING_free((ASN1_STRING *)*pval);
*pval = NULL;
break;
}
*pval = NULL;
}

View File

@ -0,0 +1,398 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine);
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
{
ASN1_VALUE *ret = NULL;
if (ASN1_item_ex_new(&ret, it) > 0)
return ret;
return NULL;
}
/* Allocate an ASN1 structure */
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
return asn1_item_ex_combine_new(pval, it, 0);
}
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine)
{
const ASN1_TEMPLATE *tt = NULL;
const ASN1_COMPAT_FUNCS *cf;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb;
ASN1_VALUE **pseqval;
int i;
if (aux && aux->asn1_cb)
asn1_cb = aux->asn1_cb;
else
asn1_cb = 0;
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_push_info(it->sname);
#endif
switch(it->itype)
{
case ASN1_ITYPE_EXTERN:
ef = it->funcs;
if (ef && ef->asn1_ex_new)
{
if (!ef->asn1_ex_new(pval, it))
goto memerr;
}
break;
case ASN1_ITYPE_COMPAT:
cf = it->funcs;
if (cf && cf->asn1_new) {
*pval = cf->asn1_new();
if (!*pval)
goto memerr;
}
break;
case ASN1_ITYPE_PRIMITIVE:
if (it->templates)
{
if (!ASN1_template_new(pval, it->templates))
goto memerr;
}
else if (!ASN1_primitive_new(pval, it))
goto memerr;
break;
case ASN1_ITYPE_MSTRING:
if (!ASN1_primitive_new(pval, it))
goto memerr;
break;
case ASN1_ITYPE_CHOICE:
if (asn1_cb)
{
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
if (!i)
goto auxerr;
if (i==2)
{
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 1;
}
}
if (!combine)
{
*pval = OPENSSL_malloc(it->size);
if (!*pval)
goto memerr;
memset(*pval, 0, it->size);
}
asn1_set_choice_selector(pval, -1, it);
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr;
break;
case ASN1_ITYPE_NDEF_SEQUENCE:
case ASN1_ITYPE_SEQUENCE:
if (asn1_cb)
{
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
if (!i)
goto auxerr;
if (i==2)
{
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 1;
}
}
if (!combine)
{
*pval = OPENSSL_malloc(it->size);
if (!*pval)
goto memerr;
memset(*pval, 0, it->size);
asn1_refcount_set_one(pval, it);
asn1_enc_init(pval, it);
}
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
{
pseqval = asn1_get_field_ptr(pval, tt);
if (!ASN1_template_new(pseqval, tt))
goto memerr;
}
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr;
break;
}
#ifdef CRYPTO_MDEBUG
if (it->sname) CRYPTO_pop_info();
#endif
return 1;
memerr:
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
ASN1_item_ex_free(pval, it);
#ifdef CRYPTO_MDEBUG
if (it->sname) CRYPTO_pop_info();
#endif
return 0;
auxerr:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
ASN1_item_ex_free(pval, it);
#ifdef CRYPTO_MDEBUG
if (it->sname) CRYPTO_pop_info();
#endif
return 0;
}
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
const ASN1_EXTERN_FUNCS *ef;
switch(it->itype)
{
case ASN1_ITYPE_EXTERN:
ef = it->funcs;
if (ef && ef->asn1_ex_clear)
ef->asn1_ex_clear(pval, it);
else *pval = NULL;
break;
case ASN1_ITYPE_PRIMITIVE:
if (it->templates)
asn1_template_clear(pval, it->templates);
else
asn1_primitive_clear(pval, it);
break;
case ASN1_ITYPE_MSTRING:
asn1_primitive_clear(pval, it);
break;
case ASN1_ITYPE_COMPAT:
case ASN1_ITYPE_CHOICE:
case ASN1_ITYPE_SEQUENCE:
case ASN1_ITYPE_NDEF_SEQUENCE:
*pval = NULL;
break;
}
}
int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
int ret;
if (tt->flags & ASN1_TFLG_OPTIONAL)
{
asn1_template_clear(pval, tt);
return 1;
}
/* If ANY DEFINED BY nothing to do */
if (tt->flags & ASN1_TFLG_ADB_MASK)
{
*pval = NULL;
return 1;
}
#ifdef CRYPTO_MDEBUG
if (tt->field_name)
CRYPTO_push_info(tt->field_name);
#endif
/* If SET OF or SEQUENCE OF, its a STACK */
if (tt->flags & ASN1_TFLG_SK_MASK)
{
STACK_OF(ASN1_VALUE) *skval;
skval = sk_ASN1_VALUE_new_null();
if (!skval)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
ret = 0;
goto done;
}
*pval = (ASN1_VALUE *)skval;
ret = 1;
goto done;
}
/* Otherwise pass it back to the item routine */
ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
done:
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return ret;
}
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
/* If ADB or STACK just NULL the field */
if (tt->flags & (ASN1_TFLG_ADB_MASK|ASN1_TFLG_SK_MASK))
*pval = NULL;
else
asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
}
/* NB: could probably combine most of the real XXX_new() behaviour and junk
* all the old functions.
*/
int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
ASN1_TYPE *typ;
ASN1_STRING *str;
int utype;
if (!it)
return 0;
if (it->funcs)
{
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
if (pf->prim_new)
return pf->prim_new(pval, it);
}
if (it->itype == ASN1_ITYPE_MSTRING)
utype = -1;
else
utype = it->utype;
switch(utype)
{
case V_ASN1_OBJECT:
*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
return 1;
case V_ASN1_BOOLEAN:
*(ASN1_BOOLEAN *)pval = it->size;
return 1;
case V_ASN1_NULL:
*pval = (ASN1_VALUE *)1;
return 1;
case V_ASN1_ANY:
typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
if (!typ)
return 0;
typ->value.ptr = NULL;
typ->type = -1;
*pval = (ASN1_VALUE *)typ;
break;
default:
str = ASN1_STRING_type_new(utype);
if (it->itype == ASN1_ITYPE_MSTRING && str)
str->flags |= ASN1_STRING_FLAG_MSTRING;
*pval = (ASN1_VALUE *)str;
break;
}
if (*pval)
return 1;
return 0;
}
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
int utype;
if (it && it->funcs)
{
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
if (pf->prim_clear)
pf->prim_clear(pval, it);
else
*pval = NULL;
return;
}
if (!it || (it->itype == ASN1_ITYPE_MSTRING))
utype = -1;
else
utype = it->utype;
if (utype == V_ASN1_BOOLEAN)
*(ASN1_BOOLEAN *)pval = it->size;
else *pval = NULL;
}

View File

@ -0,0 +1,642 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <time.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/obj.h>
#include <openssl/mem.h>
#include "asn1_locl.h"
/* Print routines.
*/
/* ASN1_PCTX routines */
ASN1_PCTX default_pctx =
{
ASN1_PCTX_FLAGS_SHOW_ABSENT, /* flags */
0, /* nm_flags */
0, /* cert_flags */
0, /* oid_flags */
0 /* str_flags */
};
ASN1_PCTX *ASN1_PCTX_new(void)
{
ASN1_PCTX *ret;
ret = OPENSSL_malloc(sizeof(ASN1_PCTX));
if (ret == NULL)
{
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->flags = 0;
ret->nm_flags = 0;
ret->cert_flags = 0;
ret->oid_flags = 0;
ret->str_flags = 0;
return ret;
}
void ASN1_PCTX_free(ASN1_PCTX *p)
{
OPENSSL_free(p);
}
unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p)
{
return p->flags;
}
void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
{
p->flags = flags;
}
unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p)
{
return p->nm_flags;
}
void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
{
p->nm_flags = flags;
}
unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p)
{
return p->cert_flags;
}
void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
{
p->cert_flags = flags;
}
unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p)
{
return p->oid_flags;
}
void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
{
p->oid_flags = flags;
}
unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p)
{
return p->str_flags;
}
void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
{
p->str_flags = flags;
}
/* Main print routines */
static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
const ASN1_ITEM *it,
const char *fname, const char *sname,
int nohdr, const ASN1_PCTX *pctx);
int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
const ASN1_ITEM *it, int indent,
const char *fname, const char *sname,
const ASN1_PCTX *pctx);
static int asn1_print_fsname(BIO *out, int indent,
const char *fname, const char *sname,
const ASN1_PCTX *pctx);
int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
const ASN1_ITEM *it, const ASN1_PCTX *pctx)
{
const char *sname;
if (pctx == NULL)
pctx = &default_pctx;
if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
sname = NULL;
else
sname = it->sname;
return asn1_item_print_ctx(out, &ifld, indent, it,
NULL, sname, 0, pctx);
}
static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
const ASN1_ITEM *it,
const char *fname, const char *sname,
int nohdr, const ASN1_PCTX *pctx)
{
const ASN1_TEMPLATE *tt;
const ASN1_EXTERN_FUNCS *ef;
ASN1_VALUE **tmpfld;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb;
ASN1_PRINT_ARG parg;
int i;
if (aux && aux->asn1_cb)
{
parg.out = out;
parg.indent = indent;
parg.pctx = pctx;
asn1_cb = aux->asn1_cb;
}
else asn1_cb = 0;
if(*fld == NULL)
{
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT)
{
if (!nohdr && !asn1_print_fsname(out, indent,
fname, sname, pctx))
return 0;
if (BIO_puts(out, "<ABSENT>\n") <= 0)
return 0;
}
return 1;
}
switch(it->itype)
{
case ASN1_ITYPE_PRIMITIVE:
if(it->templates)
{
if (!asn1_template_print_ctx(out, fld, indent,
it->templates, pctx))
return 0;
break;
}
/* fall thru */
case ASN1_ITYPE_MSTRING:
if (!asn1_primitive_print(out, fld, it,
indent, fname, sname,pctx))
return 0;
break;
case ASN1_ITYPE_EXTERN:
if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
return 0;
/* Use new style print routine if possible */
ef = it->funcs;
if (ef && ef->asn1_ex_print)
{
i = ef->asn1_ex_print(out, fld, indent, "", pctx);
if (!i)
return 0;
if ((i == 2) && (BIO_puts(out, "\n") <= 0))
return 0;
return 1;
}
else if (sname &&
BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
return 0;
break;
case ASN1_ITYPE_CHOICE:
#if 0
if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
return 0;
#endif
/* CHOICE type, get selector */
i = asn1_get_choice_selector(fld, it);
/* This should never happen... */
if((i < 0) || (i >= it->tcount))
{
if (BIO_printf(out,
"ERROR: selector [%d] invalid\n", i) <= 0)
return 0;
return 1;
}
tt = it->templates + i;
tmpfld = asn1_get_field_ptr(fld, tt);
if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
return 0;
break;
case ASN1_ITYPE_SEQUENCE:
case ASN1_ITYPE_NDEF_SEQUENCE:
if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
return 0;
if (fname || sname)
{
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
{
if (BIO_puts(out, " {\n") <= 0)
return 0;
}
else
{
if (BIO_puts(out, "\n") <= 0)
return 0;
}
}
if (asn1_cb)
{
i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
if (i == 0)
return 0;
if (i == 2)
return 1;
}
/* Print each field entry */
for(i = 0, tt = it->templates; i < it->tcount; i++, tt++)
{
const ASN1_TEMPLATE *seqtt;
seqtt = asn1_do_adb(fld, tt, 1);
if (!seqtt)
return 0;
tmpfld = asn1_get_field_ptr(fld, seqtt);
if (!asn1_template_print_ctx(out, tmpfld,
indent + 2, seqtt, pctx))
return 0;
}
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
{
if (BIO_printf(out, "%*s}\n", indent, "") < 0)
return 0;
}
if (asn1_cb)
{
i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
if (i == 0)
return 0;
}
break;
default:
BIO_printf(out, "Unprocessed type %d\n", it->itype);
return 0;
}
return 1;
}
int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
{
int flags;
size_t i;
const char *sname, *fname;
flags = tt->flags;
if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
sname = ASN1_ITEM_ptr(tt->item)->sname;
else
sname = NULL;
if(pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
fname = NULL;
else
fname = tt->field_name;
if(flags & ASN1_TFLG_SK_MASK)
{
const char *tname;
ASN1_VALUE *skitem;
STACK_OF(ASN1_VALUE) *stack;
/* SET OF, SEQUENCE OF */
if (fname)
{
if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF)
{
if(flags & ASN1_TFLG_SET_OF)
tname = "SET";
else
tname = "SEQUENCE";
if (BIO_printf(out, "%*s%s OF %s {\n",
indent, "", tname, tt->field_name) <= 0)
return 0;
}
else if (BIO_printf(out, "%*s%s:\n", indent, "",
fname) <= 0)
return 0;
}
stack = (STACK_OF(ASN1_VALUE) *)*fld;
for(i = 0; i < sk_ASN1_VALUE_num(stack); i++)
{
if ((i > 0) && (BIO_puts(out, "\n") <= 0))
return 0;
skitem = sk_ASN1_VALUE_value(stack, i);
if (!asn1_item_print_ctx(out, &skitem, indent + 2,
ASN1_ITEM_ptr(tt->item), NULL, NULL, 1, pctx))
return 0;
}
if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
return 0;
if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
{
if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
return 0;
}
return 1;
}
return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item),
fname, sname, 0, pctx);
}
static int asn1_print_fsname(BIO *out, int indent,
const char *fname, const char *sname,
const ASN1_PCTX *pctx)
{
static char spaces[] = " ";
const int nspaces = sizeof(spaces) - 1;
#if 0
if (!sname && !fname)
return 1;
#endif
while (indent > nspaces)
{
if (BIO_write(out, spaces, nspaces) != nspaces)
return 0;
indent -= nspaces;
}
if (BIO_write(out, spaces, indent) != indent)
return 0;
if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
sname = NULL;
if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
fname = NULL;
if (!sname && !fname)
return 1;
if (fname)
{
if (BIO_puts(out, fname) <= 0)
return 0;
}
if (sname)
{
if (fname)
{
if (BIO_printf(out, " (%s)", sname) <= 0)
return 0;
}
else
{
if (BIO_puts(out, sname) <= 0)
return 0;
}
}
if (BIO_write(out, ": ", 2) != 2)
return 0;
return 1;
}
static int asn1_print_boolean_ctx(BIO *out, int boolval,
const ASN1_PCTX *pctx)
{
const char *str;
switch (boolval)
{
case -1:
str = "BOOL ABSENT";
break;
case 0:
str = "FALSE";
break;
default:
str = "TRUE";
break;
}
if (BIO_puts(out, str) <= 0)
return 0;
return 1;
}
static int asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str,
const ASN1_PCTX *pctx)
{
BIGNUM *bn = NULL;
char *s = NULL;
int ret = 1;
bn = ASN1_INTEGER_to_BN(str, NULL);
if (bn == NULL) {
return 0;
}
s = BN_bn2dec(bn);
BN_free(bn);
if (s == NULL) {
return 0;
}
if (BIO_puts(out, s) <= 0) {
ret = 0;
}
OPENSSL_free(s);
return ret;
}
static int asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid,
const ASN1_PCTX *pctx)
{
char objbuf[80];
const char *ln;
ln = OBJ_nid2ln(OBJ_obj2nid(oid));
if(!ln)
ln = "";
OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
return 0;
return 1;
}
static int asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
const ASN1_PCTX *pctx)
{
if (str->type == V_ASN1_BIT_STRING)
{
if (BIO_printf(out, " (%ld unused bits)\n",
str->flags & 0x7) <= 0)
return 0;
}
else if (BIO_puts(out, "\n") <= 0)
return 0;
if (str->length > 0 && !BIO_hexdump(out, str->data, str->length, indent + 2)) {
return 0;
}
return 1;
}
static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
const ASN1_ITEM *it, int indent,
const char *fname, const char *sname,
const ASN1_PCTX *pctx)
{
long utype;
ASN1_STRING *str;
int ret = 1, needlf = 1;
const char *pname;
const ASN1_PRIMITIVE_FUNCS *pf;
pf = it->funcs;
if (!asn1_print_fsname(out, indent, fname, sname, pctx))
return 0;
if (pf && pf->prim_print)
return pf->prim_print(out, fld, it, indent, pctx);
str = (ASN1_STRING *)*fld;
if (it->itype == ASN1_ITYPE_MSTRING)
utype = str->type & ~V_ASN1_NEG;
else
utype = it->utype;
if (utype == V_ASN1_ANY)
{
ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
utype = atype->type;
fld = &atype->value.asn1_value;
str = (ASN1_STRING *)*fld;
if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
pname = NULL;
else
pname = ASN1_tag2str(utype);
}
else
{
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
pname = ASN1_tag2str(utype);
else
pname = NULL;
}
if (utype == V_ASN1_NULL)
{
if (BIO_puts(out, "NULL\n") <= 0)
return 0;
return 1;
}
if (pname)
{
if (BIO_puts(out, pname) <= 0)
return 0;
if (BIO_puts(out, ":") <= 0)
return 0;
}
switch (utype)
{
case V_ASN1_BOOLEAN:
{
int boolval = *(int *)fld;
if (boolval == -1)
boolval = it->size;
ret = asn1_print_boolean_ctx(out, boolval, pctx);
}
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
ret = asn1_print_integer_ctx(out, str, pctx);
break;
case V_ASN1_UTCTIME:
ret = ASN1_UTCTIME_print(out, str);
break;
case V_ASN1_GENERALIZEDTIME:
ret = ASN1_GENERALIZEDTIME_print(out, str);
break;
case V_ASN1_OBJECT:
ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
break;
case V_ASN1_OCTET_STRING:
case V_ASN1_BIT_STRING:
ret = asn1_print_obstring_ctx(out, str, indent, pctx);
needlf = 0;
break;
case V_ASN1_SEQUENCE:
case V_ASN1_SET:
case V_ASN1_OTHER:
if (BIO_puts(out, "\n") <= 0)
return 0;
if (ASN1_parse_dump(out, str->data, str->length,
indent, 0) <= 0)
ret = 0;
needlf = 0;
break;
default:
ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
}
if (!ret)
return 0;
if (needlf && BIO_puts(out, "\n") <= 0)
return 0;
return 1;
}

View File

@ -0,0 +1,137 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
/* Declarations for string types */
#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \
IMPLEMENT_ASN1_TYPE(sname) \
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
sname *sname##_new(void) \
{ \
return ASN1_STRING_type_new(V_##sname); \
} \
void sname##_free(sname *x) \
{ \
ASN1_STRING_free(x); \
}
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING)
IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING)
IMPLEMENT_ASN1_TYPE(ASN1_NULL);
IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL);
IMPLEMENT_ASN1_TYPE(ASN1_OBJECT);
IMPLEMENT_ASN1_TYPE(ASN1_ANY);
/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */;
IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE);
IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE);
/* Multistring types */;
IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE);
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE);
IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT);
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT);
IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING);
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING);
/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */;
IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1);
IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1);
IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0);
/* Special, OCTET STRING with indefinite length constructed support */;
IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING,
ASN1_TFLG_NDEF);
ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) = ASN1_EX_TEMPLATE_TYPE(
ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY);
ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY);
ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0,
ASN1_SET_ANY,
ASN1_ANY);
ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY);
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY,
ASN1_SEQUENCE_ANY,
ASN1_SEQUENCE_ANY);
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY,
ASN1_SET_ANY);

View File

@ -0,0 +1,266 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/err.h>
#include <openssl/thread.h>
#include "../internal.h"
/* Utility functions for manipulating fields and offsets */
/* Add 'offset' to 'addr' */
#define offset2ptr(addr, offset) (void *)(((char *) addr) + offset)
/* Given an ASN1_ITEM CHOICE type return the selector value */
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) {
int *sel = offset2ptr(*pval, it->utype);
return *sel;
}
/* Given an ASN1_ITEM CHOICE type set the selector value, return old value. */
int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
const ASN1_ITEM *it) {
int *sel, ret;
sel = offset2ptr(*pval, it->utype);
ret = *sel;
*sel = value;
return ret;
}
static CRYPTO_refcount_t *asn1_get_references(ASN1_VALUE **pval,
const ASN1_ITEM *it) {
if (it->itype != ASN1_ITYPE_SEQUENCE &&
it->itype != ASN1_ITYPE_NDEF_SEQUENCE) {
return NULL;
}
const ASN1_AUX *aux = it->funcs;
if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) {
return NULL;
}
return offset2ptr(*pval, aux->ref_offset);
}
void asn1_refcount_set_one(ASN1_VALUE **pval, const ASN1_ITEM *it) {
CRYPTO_refcount_t *references = asn1_get_references(pval, it);
if (references != NULL) {
*references = 1;
}
}
int asn1_refcount_dec_and_test_zero(ASN1_VALUE **pval, const ASN1_ITEM *it) {
CRYPTO_refcount_t *references = asn1_get_references(pval, it);
if (references != NULL) {
return CRYPTO_refcount_dec_and_test_zero(references);
}
return 1;
}
static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) {
const ASN1_AUX *aux;
if (!pval || !*pval) {
return NULL;
}
aux = it->funcs;
if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) {
return NULL;
}
return offset2ptr(*pval, aux->enc_offset);
}
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) {
ASN1_ENCODING *enc;
enc = asn1_get_enc_ptr(pval, it);
if (enc) {
enc->enc = NULL;
enc->len = 0;
enc->modified = 1;
}
}
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) {
ASN1_ENCODING *enc;
enc = asn1_get_enc_ptr(pval, it);
if (enc) {
if (enc->enc) {
OPENSSL_free(enc->enc);
}
enc->enc = NULL;
enc->len = 0;
enc->modified = 1;
}
}
int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
const ASN1_ITEM *it) {
ASN1_ENCODING *enc;
enc = asn1_get_enc_ptr(pval, it);
if (!enc) {
return 1;
}
if (enc->enc) {
OPENSSL_free(enc->enc);
}
enc->enc = OPENSSL_malloc(inlen);
if (!enc->enc) {
return 0;
}
memcpy(enc->enc, in, inlen);
enc->len = inlen;
enc->modified = 0;
return 1;
}
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
const ASN1_ITEM *it) {
ASN1_ENCODING *enc;
enc = asn1_get_enc_ptr(pval, it);
if (!enc || enc->modified) {
return 0;
}
if (out) {
memcpy(*out, enc->enc, enc->len);
*out += enc->len;
}
if (len) {
*len = enc->len;
}
return 1;
}
/* Given an ASN1_TEMPLATE get a pointer to a field */
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) {
ASN1_VALUE **pvaltmp;
if (tt->flags & ASN1_TFLG_COMBINE) {
return pval;
}
pvaltmp = offset2ptr(*pval, tt->offset);
/* NOTE for BOOLEAN types the field is just a plain int so we can't return
* int **, so settle for (int *). */
return pvaltmp;
}
/* Handle ANY DEFINED BY template, find the selector, look up the relevant
* ASN1_TEMPLATE in the table and return it. */
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
int nullerr) {
const ASN1_ADB *adb;
const ASN1_ADB_TABLE *atbl;
long selector;
ASN1_VALUE **sfld;
int i;
if (!(tt->flags & ASN1_TFLG_ADB_MASK)) {
return tt;
}
/* Else ANY DEFINED BY ... get the table */
adb = ASN1_ADB_ptr(tt->item);
/* Get the selector field */
sfld = offset2ptr(*pval, adb->offset);
/* Check if NULL */
if (!sfld) {
if (!adb->null_tt) {
goto err;
}
return adb->null_tt;
}
/* Convert type to a long:
* NB: don't check for NID_undef here because it
* might be a legitimate value in the table */
if (tt->flags & ASN1_TFLG_ADB_OID) {
selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
} else {
selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld);
}
/* Try to find matching entry in table Maybe should check application types
* first to allow application override? Might also be useful to have a flag
* which indicates table is sorted and we can do a binary search. For now
* stick to a linear search. */
for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) {
if (atbl->value == selector) {
return &atbl->tt;
}
}
/* FIXME: need to search application table too */
/* No match, return default type */
if (!adb->default_tt) {
goto err;
}
return adb->default_tt;
err:
/* FIXME: should log the value or OID of unsupported type */
if (nullerr) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
}
return NULL;
}

View File

@ -0,0 +1,142 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bn.h>
/* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER as a
* BIGNUM directly. Currently it ignores the sign which isn't a problem since all
* BIGNUMs used are non negative and anything that looks negative is normally due
* to an encoding error.
*/
#define BN_SENSITIVE 1
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
static const ASN1_PRIMITIVE_FUNCS bignum_pf = {
NULL, 0,
bn_new,
bn_free,
0,
bn_c2i,
bn_i2c
};
ASN1_ITEM_start(BIGNUM)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
ASN1_ITEM_end(BIGNUM)
ASN1_ITEM_start(CBIGNUM)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
ASN1_ITEM_end(CBIGNUM)
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
*pval = (ASN1_VALUE *)BN_new();
if(*pval) return 1;
else return 0;
}
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
if(!*pval) return;
if(it->size & BN_SENSITIVE) BN_clear_free((BIGNUM *)*pval);
else BN_free((BIGNUM *)*pval);
*pval = NULL;
}
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it)
{
BIGNUM *bn;
int pad;
if(!*pval) return -1;
bn = (BIGNUM *)*pval;
/* If MSB set in an octet we need a padding byte */
if(BN_num_bits(bn) & 0x7) pad = 0;
else pad = 1;
if(cont) {
if(pad) *cont++ = 0;
BN_bn2bin(bn, cont);
}
return pad + BN_num_bytes(bn);
}
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it)
{
BIGNUM *bn;
if(!*pval)
{
if (!bn_new(pval, it))
{
return 0;
}
}
bn = (BIGNUM *)*pval;
if(!BN_bin2bn(cont, len, bn)) {
bn_free(pval, it);
return 0;
}
return 1;
}

View File

@ -0,0 +1,182 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/asn1.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/mem.h>
/* Custom primitive type for long handling. This converts between an ASN1_INTEGER
* and a long directly.
*/
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx);
static const ASN1_PRIMITIVE_FUNCS long_pf = {
NULL, 0,
long_new,
long_free,
long_free, /* Clear should set to initial value */
long_c2i,
long_i2c,
long_print
};
ASN1_ITEM_start(LONG)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
ASN1_ITEM_end(LONG)
ASN1_ITEM_start(ZLONG)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
ASN1_ITEM_end(ZLONG)
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
*(long *)pval = it->size;
return 1;
}
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
*(long *)pval = it->size;
}
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it)
{
long ltmp;
unsigned long utmp;
int clen, pad, i;
/* this exists to bypass broken gcc optimization */
char *cp = (char *)pval;
/* use memcpy, because we may not be long aligned */
memcpy(&ltmp, cp, sizeof(long));
if(ltmp == it->size) return -1;
/* Convert the long to positive: we subtract one if negative so
* we can cleanly handle the padding if only the MSB of the leading
* octet is set.
*/
if(ltmp < 0) utmp = -ltmp - 1;
else utmp = ltmp;
clen = BN_num_bits_word(utmp);
/* If MSB of leading octet set we need to pad */
if(!(clen & 0x7)) pad = 1;
else pad = 0;
/* Convert number of bits to number of octets */
clen = (clen + 7) >> 3;
if(cont) {
if(pad) *cont++ = (ltmp < 0) ? 0xff : 0;
for(i = clen - 1; i >= 0; i--) {
cont[i] = (unsigned char)(utmp & 0xff);
if(ltmp < 0) cont[i] ^= 0xff;
utmp >>= 8;
}
}
return clen + pad;
}
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it)
{
int neg, i;
long ltmp;
unsigned long utmp = 0;
char *cp = (char *)pval;
if(len > (int)sizeof(long)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
return 0;
}
/* Is it negative? */
if(len && (cont[0] & 0x80)) neg = 1;
else neg = 0;
utmp = 0;
for(i = 0; i < len; i++) {
utmp <<= 8;
if(neg) utmp |= cont[i] ^ 0xff;
else utmp |= cont[i];
}
ltmp = (long)utmp;
if(neg) {
ltmp++;
ltmp = -ltmp;
}
if(ltmp == it->size) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
return 0;
}
memcpy(cp, &ltmp, sizeof(long));
return 1;
}
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx)
{
return BIO_printf(out, "%ld\n", *(long *)pval);
}

View File

@ -0,0 +1,9 @@
include_directories(. .. ../../include)
add_library(
base64
OBJECT
base64.c
)

View File

@ -0,0 +1,478 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/base64.h>
#include <assert.h>
#include <limits.h>
#include <string.h>
static const unsigned char data_bin2ascii[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define conv_bin2ascii(a) (data_bin2ascii[(a) & 0x3f])
/* 64 char lines
* pad input with 0
* left over chars are set to =
* 1 byte => xx==
* 2 bytes => xxx=
* 3 bytes => xxxx
*/
#define BIN_PER_LINE (64/4*3)
#define CHUNKS_PER_LINE (64/4)
#define CHAR_PER_LINE (64+1)
/* 0xF0 is a EOLN
* 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
* 0xF2 is EOF
* 0xE0 is ignore at start of line.
* 0xFF is error */
#define B64_EOLN 0xF0
#define B64_CR 0xF1
#define B64_EOF 0xF2
#define B64_WS 0xE0
#define B64_ERROR 0xFF
#define B64_NOT_BASE64(a) (((a) | 0x13) == 0xF3)
static const uint8_t data_ascii2bin[128] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xF0, 0xFF,
0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
static uint8_t conv_ascii2bin(uint8_t a) {
if (a >= 128) {
return 0xFF;
}
return data_ascii2bin[a];
}
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) {
ctx->length = 48;
ctx->num = 0;
ctx->line_num = 0;
}
void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
const uint8_t *in, size_t in_len) {
unsigned i, j;
unsigned total = 0;
*out_len = 0;
if (in_len == 0) {
return;
}
assert(ctx->length <= sizeof(ctx->enc_data));
if (ctx->num + in_len < ctx->length) {
memcpy(&ctx->enc_data[ctx->num], in, in_len);
ctx->num += in_len;
return;
}
if (ctx->num != 0) {
i = ctx->length - ctx->num;
memcpy(&ctx->enc_data[ctx->num], in, i);
in += i;
in_len -= i;
j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
ctx->num = 0;
out += j;
*(out++) = '\n';
*out = '\0';
total = j + 1;
}
while (in_len >= ctx->length) {
j = EVP_EncodeBlock(out, in, ctx->length);
in += ctx->length;
in_len -= ctx->length;
out += j;
*(out++) = '\n';
*out = '\0';
total += j + 1;
}
if (in_len != 0) {
memcpy(&ctx->enc_data[0], in, in_len);
}
ctx->num = in_len;
*out_len = total;
}
void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
unsigned ret = 0;
if (ctx->num != 0) {
ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
out[ret++] = '\n';
out[ret] = '\0';
ctx->num = 0;
}
*out_len = ret;
}
size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
uint32_t l;
size_t remaining = src_len, ret = 0;
while (remaining) {
if (remaining >= 3) {
l = (((uint32_t)src[0]) << 16L) | (((uint32_t)src[1]) << 8L) | src[2];
*(dst++) = conv_bin2ascii(l >> 18L);
*(dst++) = conv_bin2ascii(l >> 12L);
*(dst++) = conv_bin2ascii(l >> 6L);
*(dst++) = conv_bin2ascii(l);
remaining -= 3;
} else {
l = ((uint32_t)src[0]) << 16L;
if (remaining == 2) {
l |= ((uint32_t)src[1] << 8L);
}
*(dst++) = conv_bin2ascii(l >> 18L);
*(dst++) = conv_bin2ascii(l >> 12L);
*(dst++) = (remaining == 1) ? '=' : conv_bin2ascii(l >> 6L);
*(dst++) = '=';
remaining = 0;
}
ret += 4;
src += 3;
}
*dst = '\0';
return ret;
}
int EVP_DecodedLength(size_t *out_len, size_t len) {
if (len % 4 != 0) {
return 0;
}
*out_len = (len / 4) * 3;
return 1;
}
int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out,
const uint8_t *in, size_t in_len) {
uint8_t a, b, c, d;
size_t pad_len = 0, len = 0, max_len, i;
uint32_t l;
if (!EVP_DecodedLength(&max_len, in_len) || max_out < max_len) {
return 0;
}
for (i = 0; i < in_len; i += 4) {
a = conv_ascii2bin(*(in++));
b = conv_ascii2bin(*(in++));
if (i + 4 == in_len && in[1] == '=') {
if (in[0] == '=') {
pad_len = 2;
} else {
pad_len = 1;
}
}
if (pad_len < 2) {
c = conv_ascii2bin(*(in++));
} else {
c = 0;
}
if (pad_len < 1) {
d = conv_ascii2bin(*(in++));
} else {
d = 0;
}
if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) {
return 0;
}
l = ((((uint32_t)a) << 18L) | (((uint32_t)b) << 12L) |
(((uint32_t)c) << 6L) | (((uint32_t)d)));
*(out++) = (uint8_t)(l >> 16L) & 0xff;
if (pad_len < 2) {
*(out++) = (uint8_t)(l >> 8L) & 0xff;
}
if (pad_len < 1) {
*(out++) = (uint8_t)(l) & 0xff;
}
len += 3 - pad_len;
}
*out_len = len;
return 1;
}
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
ctx->length = 30;
ctx->num = 0;
ctx->line_num = 0;
ctx->expect_nl = 0;
}
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
const uint8_t *in, size_t in_len) {
int seof = -1, eof = 0, rv = -1, v, tmp, exp_nl;
uint8_t *d;
unsigned i, n, ln, ret = 0;
n = ctx->num;
d = ctx->enc_data;
ln = ctx->line_num;
exp_nl = ctx->expect_nl;
/* last line of input. */
if (in_len == 0 || (n == 0 && conv_ascii2bin(in[0]) == B64_EOF)) {
rv = 0;
goto end;
}
/* We parse the input data */
for (i = 0; i < in_len; i++) {
/* If the current line is > 80 characters, scream alot */
if (ln >= 80) {
rv = -1;
goto end;
}
/* Get char and put it into the buffer */
tmp = *(in++);
v = conv_ascii2bin(tmp);
/* only save the good data :-) */
if (!B64_NOT_BASE64(v)) {
assert(n < sizeof(ctx->enc_data));
d[n++] = tmp;
ln++;
} else if (v == B64_ERROR) {
rv = -1;
goto end;
}
/* have we seen a '=' which is 'definitly' the last
* input line. seof will point to the character that
* holds it. and eof will hold how many characters to
* chop off. */
if (tmp == '=') {
if (seof == -1) {
seof = n;
}
eof++;
if (eof > 2) {
/* There are, at most, two equals signs at the end of base64 data. */
rv = -1;
goto end;
}
}
if (v == B64_CR) {
ln = 0;
if (exp_nl) {
continue;
}
}
/* eoln */
if (v == B64_EOLN) {
ln = 0;
if (exp_nl) {
exp_nl = 0;
continue;
}
}
exp_nl = 0;
/* If we are at the end of input and it looks like a
* line, process it. */
if ((i + 1) == in_len && (((n & 3) == 0) || eof)) {
v = B64_EOF;
/* In case things were given us in really small
records (so two '=' were given in separate
updates), eof may contain the incorrect number
of ending bytes to skip, so let's redo the count */
eof = 0;
if (d[n - 1] == '=') {
eof++;
}
if (d[n - 2] == '=') {
eof++;
}
/* There will never be more than two '=' */
}
if ((v == B64_EOF && (n & 3) == 0) || n >= 64) {
/* This is needed to work correctly on 64 byte input
* lines. We process the line and then need to
* accept the '\n' */
if (v != B64_EOF && n >= 64) {
exp_nl = 1;
}
if (n > 0) {
/* TODO(davidben): Switch this to EVP_DecodeBase64. */
v = EVP_DecodeBlock(out, d, n);
n = 0;
if (v < 0) {
rv = 0;
goto end;
}
if (eof > v) {
rv = -1;
goto end;
}
ret += (v - eof);
} else {
eof = 1;
v = 0;
}
/* This is the case where we have had a short
* but valid input line */
if (v < (int)ctx->length && eof) {
rv = 0;
goto end;
} else {
ctx->length = v;
}
if (seof >= 0) {
rv = 0;
goto end;
}
out += v;
}
}
rv = 1;
end:
*out_len = ret;
ctx->num = n;
ctx->line_num = ln;
ctx->expect_nl = exp_nl;
return rv;
}
int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *outl) {
int i;
*outl = 0;
if (ctx->num != 0) {
/* TODO(davidben): Switch this to EVP_DecodeBase64. */
i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
if (i < 0) {
return -1;
}
ctx->num = 0;
*outl = i;
return 1;
} else {
return 1;
}
}
int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
size_t dst_len;
/* trim white space from the start of the line. */
while (conv_ascii2bin(*src) == B64_WS && src_len > 0) {
src++;
src_len--;
}
/* strip off stuff at the end of the line
* ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */
while (src_len > 3 && B64_NOT_BASE64(conv_ascii2bin(src[src_len - 1]))) {
src_len--;
}
if (!EVP_DecodedLength(&dst_len, src_len) || dst_len > INT_MAX) {
return -1;
}
if (!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) {
return -1;
}
/* EVP_DecodeBlock does not take padding into account, so put the
* NULs back in... so the caller can strip them back out. */
while (dst_len % 3 != 0) {
dst[dst_len++] = '\0';
}
assert(dst_len <= INT_MAX);
return dst_len;
}
int EVP_EncodedLength(size_t *out_len, size_t len) {
if (len + 2 < len) {
return 0;
}
len += 2;
len /= 3;
if (((len << 2) >> 2) != len) {
return 0;
}
len <<= 2;
if (len + 1 < len) {
return 0;
}
len++;
*out_len = len;
return 1;
}

View File

@ -0,0 +1,19 @@
include_directories(. .. ../../include)
add_library(
bio
OBJECT
bio.c
bio_mem.c
buffer.c
connect.c
fd.c
file.c
hexdump.c
pair.c
printf.c
socket.c
socket_helper.c
)

View File

@ -0,0 +1,606 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/thread.h>
#include "../internal.h"
/* BIO_set initialises a BIO structure to have the given type and sets the
* reference count to one. It returns one on success or zero on error. */
static int bio_set(BIO *bio, const BIO_METHOD *method) {
/* This function can be called with a stack allocated |BIO| so we have to
* assume that the contents of |BIO| are arbitary. This also means that it'll
* leak memory if you call |BIO_set| twice on the same BIO. */
memset(bio, 0, sizeof(BIO));
bio->method = method;
bio->shutdown = 1;
bio->references = 1;
if (method->create != NULL && !method->create(bio)) {
return 0;
}
return 1;
}
BIO *BIO_new(const BIO_METHOD *method) {
BIO *ret = OPENSSL_malloc(sizeof(BIO));
if (ret == NULL) {
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (!bio_set(ret, method)) {
OPENSSL_free(ret);
ret = NULL;
}
return ret;
}
int BIO_free(BIO *bio) {
BIO *next_bio;
for (; bio != NULL; bio = next_bio) {
if (!CRYPTO_refcount_dec_and_test_zero(&bio->references)) {
return 0;
}
if (bio->callback != NULL) {
int i = (int)bio->callback(bio, BIO_CB_FREE, NULL, 0, 0, 1);
if (i <= 0) {
return i;
}
}
next_bio = BIO_pop(bio);
if (bio->method != NULL && bio->method->destroy != NULL) {
bio->method->destroy(bio);
}
OPENSSL_free(bio);
}
return 1;
}
BIO *BIO_up_ref(BIO *bio) {
CRYPTO_refcount_inc(&bio->references);
return bio;
}
void BIO_vfree(BIO *bio) {
BIO_free(bio);
}
void BIO_free_all(BIO *bio) {
BIO_free(bio);
}
static int bio_io(BIO *bio, void *buf, int len, size_t method_offset,
int callback_flags, size_t *num) {
int i;
typedef int (*io_func_t)(BIO *, char *, int);
io_func_t io_func = NULL;
if (bio != NULL && bio->method != NULL) {
io_func =
*((const io_func_t *)(((const uint8_t *)bio->method) + method_offset));
}
if (io_func == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (bio->callback != NULL) {
i = (int) bio->callback(bio, callback_flags, buf, len, 0L, 1L);
if (i <= 0) {
return i;
}
}
if (!bio->init) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
return -2;
}
i = 0;
if (buf != NULL && len > 0) {
i = io_func(bio, buf, len);
}
if (i > 0) {
*num += i;
}
if (bio->callback != NULL) {
i = (int)(bio->callback(bio, callback_flags | BIO_CB_RETURN, buf, len, 0L,
(long)i));
}
return i;
}
int BIO_read(BIO *bio, void *buf, int len) {
return bio_io(bio, buf, len, offsetof(BIO_METHOD, bread), BIO_CB_READ,
&bio->num_read);
}
int BIO_gets(BIO *bio, char *buf, int len) {
return bio_io(bio, buf, len, offsetof(BIO_METHOD, bgets), BIO_CB_GETS,
&bio->num_read);
}
int BIO_write(BIO *bio, const void *in, int inl) {
return bio_io(bio, (char *)in, inl, offsetof(BIO_METHOD, bwrite),
BIO_CB_WRITE, &bio->num_write);
}
int BIO_puts(BIO *bio, const char *in) {
return BIO_write(bio, in, strlen(in));
}
int BIO_flush(BIO *bio) {
return BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, NULL);
}
long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) {
long ret;
if (bio == NULL) {
return 0;
}
if (bio->method == NULL || bio->method->ctrl == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return -2;
}
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_CTRL, parg, cmd, larg, 1);
if (ret <= 0) {
return ret;
}
}
ret = bio->method->ctrl(bio, cmd, larg, parg);
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_CTRL | BIO_CB_RETURN, parg, cmd, larg, ret);
}
return ret;
}
char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) {
char *p = NULL;
if (BIO_ctrl(b, cmd, larg, (void *)&p) <= 0) {
return NULL;
}
return p;
}
long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) {
int i = iarg;
return BIO_ctrl(b, cmd, larg, (void *)&i);
}
int BIO_reset(BIO *bio) {
return BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL);
}
void BIO_set_flags(BIO *bio, int flags) {
bio->flags |= flags;
}
int BIO_test_flags(const BIO *bio, int flags) {
return bio->flags & flags;
}
int BIO_should_read(const BIO *bio) {
return BIO_test_flags(bio, BIO_FLAGS_READ);
}
int BIO_should_write(const BIO *bio) {
return BIO_test_flags(bio, BIO_FLAGS_WRITE);
}
int BIO_should_retry(const BIO *bio) {
return BIO_test_flags(bio, BIO_FLAGS_SHOULD_RETRY);
}
int BIO_should_io_special(const BIO *bio) {
return BIO_test_flags(bio, BIO_FLAGS_IO_SPECIAL);
}
int BIO_get_retry_reason(const BIO *bio) { return bio->retry_reason; }
void BIO_clear_flags(BIO *bio, int flags) {
bio->flags &= ~flags;
}
void BIO_set_retry_read(BIO *bio) {
bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY;
}
void BIO_set_retry_write(BIO *bio) {
bio->flags |= BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY;
}
static const int kRetryFlags = BIO_FLAGS_RWS | BIO_FLAGS_SHOULD_RETRY;
int BIO_get_retry_flags(BIO *bio) {
return bio->flags & kRetryFlags;
}
void BIO_clear_retry_flags(BIO *bio) {
bio->flags &= ~kRetryFlags;
bio->retry_reason = 0;
}
int BIO_method_type(const BIO *bio) { return bio->method->type; }
void BIO_copy_next_retry(BIO *bio) {
BIO_clear_retry_flags(bio);
BIO_set_flags(bio, BIO_get_retry_flags(bio->next_bio));
bio->retry_reason = bio->next_bio->retry_reason;
}
long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
long ret;
bio_info_cb cb;
if (bio == NULL) {
return 0;
}
if (bio->method == NULL || bio->method->callback_ctrl == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return 0;
}
cb = bio->callback;
if (cb != NULL) {
ret = cb(bio, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L);
if (ret <= 0) {
return ret;
}
}
ret = bio->method->callback_ctrl(bio, cmd, fp);
if (cb != NULL) {
ret = cb(bio, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, cmd, 0, ret);
}
return ret;
}
size_t BIO_pending(const BIO *bio) {
return BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL);
}
size_t BIO_ctrl_pending(const BIO *bio) {
return BIO_pending(bio);
}
size_t BIO_wpending(const BIO *bio) {
return BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL);
}
int BIO_set_close(BIO *bio, int close_flag) {
return BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, close_flag, NULL);
}
void BIO_set_callback(BIO *bio, bio_info_cb callback_func) {
bio->callback = callback_func;
}
void BIO_set_callback_arg(BIO *bio, char *arg) {
bio->cb_arg = arg;
}
char *BIO_get_callback_arg(const BIO *bio) {
return bio->cb_arg;
}
OPENSSL_EXPORT size_t BIO_number_read(const BIO *bio) {
return bio->num_read;
}
OPENSSL_EXPORT size_t BIO_number_written(const BIO *bio) {
return bio->num_write;
}
BIO *BIO_push(BIO *bio, BIO *appended_bio) {
BIO *last_bio;
if (bio == NULL) {
return bio;
}
last_bio = bio;
while (last_bio->next_bio != NULL) {
last_bio = last_bio->next_bio;
}
last_bio->next_bio = appended_bio;
return bio;
}
BIO *BIO_pop(BIO *bio) {
BIO *ret;
if (bio == NULL) {
return NULL;
}
ret = bio->next_bio;
bio->next_bio = NULL;
return ret;
}
BIO *BIO_next(BIO *bio) {
if (!bio) {
return NULL;
}
return bio->next_bio;
}
BIO *BIO_find_type(BIO *bio, int type) {
int method_type, mask;
if (!bio) {
return NULL;
}
mask = type & 0xff;
do {
if (bio->method != NULL) {
method_type = bio->method->type;
if (!mask) {
if (method_type & type) {
return bio;
}
} else if (method_type == type) {
return bio;
}
}
bio = bio->next_bio;
} while (bio != NULL);
return NULL;
}
int BIO_indent(BIO *bio, unsigned indent, unsigned max_indent) {
if (indent > max_indent) {
indent = max_indent;
}
while (indent--) {
if (BIO_puts(bio, " ") != 1) {
return 0;
}
}
return 1;
}
static int print_bio(const char *str, size_t len, void *bio) {
return BIO_write((BIO *)bio, str, len);
}
void BIO_print_errors(BIO *bio) {
ERR_print_errors_cb(print_bio, bio);
}
void ERR_print_errors(BIO *bio) {
BIO_print_errors(bio);
}
/* bio_read_all reads everything from |bio| and prepends |prefix| to it. On
* success, |*out| is set to an allocated buffer (which should be freed with
* |OPENSSL_free|), |*out_len| is set to its length and one is returned. The
* buffer will contain |prefix| followed by the contents of |bio|. On failure,
* zero is returned.
*
* The function will fail if the size of the output would equal or exceed
* |max_len|. */
static int bio_read_all(BIO *bio, uint8_t **out, size_t *out_len,
const uint8_t *prefix, size_t prefix_len,
size_t max_len) {
static const size_t kChunkSize = 4096;
size_t len = prefix_len + kChunkSize;
if (len > max_len) {
len = max_len;
}
if (len < prefix_len) {
return 0;
}
*out = OPENSSL_malloc(len);
if (*out == NULL) {
return 0;
}
memcpy(*out, prefix, prefix_len);
size_t done = prefix_len;
for (;;) {
if (done == len) {
OPENSSL_free(*out);
return 0;
}
const size_t todo = len - done;
assert(todo < INT_MAX);
const int n = BIO_read(bio, *out + done, todo);
if (n == 0) {
*out_len = done;
return 1;
} else if (n == -1) {
OPENSSL_free(*out);
return 0;
}
done += n;
if (len < max_len && len - done < kChunkSize / 2) {
len += kChunkSize;
if (len < kChunkSize || len > max_len) {
len = max_len;
}
uint8_t *new_buf = OPENSSL_realloc(*out, len);
if (new_buf == NULL) {
OPENSSL_free(*out);
return 0;
}
*out = new_buf;
}
}
}
int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) {
uint8_t header[6];
static const size_t kInitialHeaderLen = 2;
if (BIO_read(bio, header, kInitialHeaderLen) != kInitialHeaderLen) {
return 0;
}
const uint8_t tag = header[0];
const uint8_t length_byte = header[1];
if ((tag & 0x1f) == 0x1f) {
/* Long form tags are not supported. */
return 0;
}
size_t len, header_len;
if ((length_byte & 0x80) == 0) {
/* Short form length. */
len = length_byte;
header_len = kInitialHeaderLen;
} else {
const size_t num_bytes = length_byte & 0x7f;
if ((tag & 0x20 /* constructed */) != 0 && num_bytes == 0) {
/* indefinite length. */
return bio_read_all(bio, out, out_len, header, kInitialHeaderLen,
max_len);
}
if (num_bytes == 0 || num_bytes > 4) {
return 0;
}
if (BIO_read(bio, header + kInitialHeaderLen, num_bytes) != num_bytes) {
return 0;
}
header_len = kInitialHeaderLen + num_bytes;
uint32_t len32 = 0;
unsigned i;
for (i = 0; i < num_bytes; i++) {
len32 <<= 8;
len32 |= header[kInitialHeaderLen + i];
}
if (len32 < 128) {
/* Length should have used short-form encoding. */
return 0;
}
if ((len32 >> ((num_bytes-1)*8)) == 0) {
/* Length should have been at least one byte shorter. */
return 0;
}
len = len32;
}
if (len + header_len < len ||
len + header_len > max_len) {
return 0;
}
len += header_len;
*out_len = len;
*out = OPENSSL_malloc(len);
if (*out == NULL) {
return 0;
}
memcpy(*out, header, header_len);
if (BIO_read(bio, (*out) + header_len, len - header_len) !=
len - header_len) {
OPENSSL_free(*out);
return 0;
}
return 1;
}

View File

@ -0,0 +1,327 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <limits.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
BIO *BIO_new_mem_buf(void *buf, int len) {
BIO *ret;
BUF_MEM *b;
const size_t size = len < 0 ? strlen((char *)buf) : (size_t)len;
if (!buf && len != 0) {
OPENSSL_PUT_ERROR(BIO, BIO_R_NULL_PARAMETER);
return NULL;
}
ret = BIO_new(BIO_s_mem());
if (ret == NULL) {
return NULL;
}
b = (BUF_MEM *)ret->ptr;
b->data = buf;
b->length = size;
b->max = size;
ret->flags |= BIO_FLAGS_MEM_RDONLY;
/* |num| is used to store the value that this BIO will return when it runs
* out of data. If it's negative then the retry flags will also be set. Since
* this is static data, retrying wont help */
ret->num = 0;
return ret;
}
static int mem_new(BIO *bio) {
BUF_MEM *b;
b = BUF_MEM_new();
if (b == NULL) {
return 0;
}
/* |shutdown| is used to store the close flag: whether the BIO has ownership
* of the BUF_MEM. */
bio->shutdown = 1;
bio->init = 1;
bio->num = -1;
bio->ptr = (char *)b;
return 1;
}
static int mem_free(BIO *bio) {
BUF_MEM *b;
if (bio == NULL) {
return 0;
}
if (!bio->shutdown || !bio->init || bio->ptr == NULL) {
return 1;
}
b = (BUF_MEM *)bio->ptr;
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
b->data = NULL;
}
BUF_MEM_free(b);
bio->ptr = NULL;
return 1;
}
static int mem_read(BIO *bio, char *out, int outl) {
int ret;
BUF_MEM *b = (BUF_MEM*) bio->ptr;
BIO_clear_retry_flags(bio);
ret = outl;
if (b->length < INT_MAX && ret > (int)b->length) {
ret = b->length;
}
if (ret > 0) {
memcpy(out, b->data, ret);
b->length -= ret;
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
b->data += ret;
} else {
memmove(b->data, &b->data[ret], b->length);
}
} else if (b->length == 0) {
ret = bio->num;
if (ret != 0) {
BIO_set_retry_read(bio);
}
}
return ret;
}
static int mem_write(BIO *bio, const char *in, int inl) {
int ret = -1;
int blen;
BUF_MEM *b;
b = (BUF_MEM *)bio->ptr;
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
OPENSSL_PUT_ERROR(BIO, BIO_R_WRITE_TO_READ_ONLY_BIO);
goto err;
}
BIO_clear_retry_flags(bio);
blen = b->length;
if (INT_MAX - blen < inl) {
goto err;
}
if (BUF_MEM_grow_clean(b, blen + inl) != (blen + inl)) {
goto err;
}
memcpy(&b->data[blen], in, inl);
ret = inl;
err:
return ret;
}
static int mem_puts(BIO *bp, const char *str) {
return mem_write(bp, str, strlen(str));
}
static int mem_gets(BIO *bio, char *buf, int size) {
int i, j;
char *p;
BUF_MEM *b = (BUF_MEM *)bio->ptr;
BIO_clear_retry_flags(bio);
j = b->length;
if (size - 1 < j) {
j = size - 1;
}
if (j <= 0) {
if (size > 0) {
*buf = 0;
}
return 0;
}
p = b->data;
for (i = 0; i < j; i++) {
if (p[i] == '\n') {
i++;
break;
}
}
/* i is now the max num of bytes to copy, either j or up to and including the
* first newline */
i = mem_read(bio, buf, i);
if (i > 0) {
buf[i] = '\0';
}
return i;
}
static long mem_ctrl(BIO *bio, int cmd, long num, void *ptr) {
long ret = 1;
char **pptr;
BUF_MEM *b = (BUF_MEM *)bio->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
if (b->data != NULL) {
/* For read only case reset to the start again */
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
b->data -= b->max - b->length;
b->length = b->max;
} else {
memset(b->data, 0, b->max);
b->length = 0;
}
}
break;
case BIO_CTRL_EOF:
ret = (long)(b->length == 0);
break;
case BIO_C_SET_BUF_MEM_EOF_RETURN:
bio->num = (int)num;
break;
case BIO_CTRL_INFO:
ret = (long)b->length;
if (ptr != NULL) {
pptr = (char **)ptr;
*pptr = (char *)&b->data[0];
}
break;
case BIO_C_SET_BUF_MEM:
mem_free(bio);
bio->shutdown = (int)num;
bio->ptr = ptr;
break;
case BIO_C_GET_BUF_MEM_PTR:
if (ptr != NULL) {
pptr = (char **)ptr;
*pptr = (char *)b;
}
break;
case BIO_CTRL_GET_CLOSE:
ret = (long)bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
break;
case BIO_CTRL_WPENDING:
ret = 0L;
break;
case BIO_CTRL_PENDING:
ret = (long)b->length;
break;
case BIO_CTRL_FLUSH:
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
static const BIO_METHOD mem_method = {
BIO_TYPE_MEM, "memory buffer", mem_write, mem_read, mem_puts,
mem_gets, mem_ctrl, mem_new, mem_free, NULL, };
const BIO_METHOD *BIO_s_mem(void) { return &mem_method; }
int BIO_mem_contents(const BIO *bio, const uint8_t **out_contents,
size_t *out_len) {
const BUF_MEM *b;
if (bio->method != &mem_method) {
return 0;
}
b = (BUF_MEM *)bio->ptr;
*out_contents = (uint8_t *)b->data;
*out_len = b->length;
return 1;
}
long BIO_get_mem_data(BIO *bio, char **contents) {
return BIO_ctrl(bio, BIO_CTRL_INFO, 0, (char *) contents);
}
int BIO_get_mem_ptr(BIO *bio, BUF_MEM **out) {
return BIO_ctrl(bio, BIO_C_GET_BUF_MEM_PTR, 0, (char *) out);
}
int BIO_set_mem_buf(BIO *bio, BUF_MEM *b, int take_ownership) {
return BIO_ctrl(bio, BIO_C_SET_BUF_MEM, take_ownership, (char *) b);
}
int BIO_set_mem_eof_return(BIO *bio, int eof_value) {
return BIO_ctrl(bio, BIO_C_SET_BUF_MEM_EOF_RETURN, eof_value, NULL);
}

View File

@ -0,0 +1,496 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#define DEFAULT_BUFFER_SIZE 4096
typedef struct bio_f_buffer_ctx_struct {
/* Buffers are setup like this:
*
* <---------------------- size ----------------------->
* +---------------------------------------------------+
* | consumed | remaining | free space |
* +---------------------------------------------------+
* <-- off --><------- len ------->
*/
int ibuf_size; /* how big is the input buffer */
int obuf_size; /* how big is the output buffer */
char *ibuf; /* the char array */
int ibuf_len; /* how many bytes are in it */
int ibuf_off; /* write/read offset */
char *obuf; /* the char array */
int obuf_len; /* how many bytes are in it */
int obuf_off; /* write/read offset */
} BIO_F_BUFFER_CTX;
static int buffer_new(BIO *bio) {
BIO_F_BUFFER_CTX *ctx;
ctx = OPENSSL_malloc(sizeof(BIO_F_BUFFER_CTX));
if (ctx == NULL) {
return 0;
}
memset(ctx, 0, sizeof(BIO_F_BUFFER_CTX));
ctx->ibuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
if (ctx->ibuf == NULL) {
goto err1;
}
ctx->obuf = (char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
if (ctx->obuf == NULL) {
goto err2;
}
ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
ctx->obuf_size = DEFAULT_BUFFER_SIZE;
bio->init = 1;
bio->ptr = (char *)ctx;
return 1;
err2:
OPENSSL_free(ctx->ibuf);
err1:
OPENSSL_free(ctx);
return 0;
}
static int buffer_free(BIO *bio) {
BIO_F_BUFFER_CTX *ctx;
if (bio == NULL || bio->ptr == NULL) {
return 0;
}
ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
OPENSSL_free(ctx->ibuf);
OPENSSL_free(ctx->obuf);
OPENSSL_free(bio->ptr);
bio->ptr = NULL;
bio->init = 0;
bio->flags = 0;
return 1;
}
static int buffer_read(BIO *bio, char *out, int outl) {
int i, num = 0;
BIO_F_BUFFER_CTX *ctx;
ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
if (ctx == NULL || bio->next_bio == NULL) {
return 0;
}
num = 0;
BIO_clear_retry_flags(bio);
for (;;) {
i = ctx->ibuf_len;
/* If there is stuff left over, grab it */
if (i != 0) {
if (i > outl) {
i = outl;
}
memcpy(out, &ctx->ibuf[ctx->ibuf_off], i);
ctx->ibuf_off += i;
ctx->ibuf_len -= i;
num += i;
if (outl == i) {
return num;
}
outl -= i;
out += i;
}
/* We may have done a partial read. Try to do more. We have nothing in the
* buffer. If we get an error and have read some data, just return it and
* let them retry to get the error again. Copy direct to parent address
* space */
if (outl > ctx->ibuf_size) {
for (;;) {
i = BIO_read(bio->next_bio, out, outl);
if (i <= 0) {
BIO_copy_next_retry(bio);
if (i < 0) {
return (num > 0) ? num : i;
}
return num;
}
num += i;
if (outl == i) {
return num;
}
out += i;
outl -= i;
}
}
/* else */
/* we are going to be doing some buffering */
i = BIO_read(bio->next_bio, ctx->ibuf, ctx->ibuf_size);
if (i <= 0) {
BIO_copy_next_retry(bio);
if (i < 0) {
return (num > 0) ? num : i;
}
return num;
}
ctx->ibuf_off = 0;
ctx->ibuf_len = i;
}
}
static int buffer_write(BIO *b, const char *in, int inl) {
int i, num = 0;
BIO_F_BUFFER_CTX *ctx;
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
if (ctx == NULL || b->next_bio == NULL) {
return 0;
}
BIO_clear_retry_flags(b);
for (;;) {
i = ctx->obuf_size - (ctx->obuf_off + ctx->obuf_len);
/* add to buffer and return */
if (i >= inl) {
memcpy(&ctx->obuf[ctx->obuf_off + ctx->obuf_len], in, inl);
ctx->obuf_len += inl;
return num + inl;
}
/* else */
/* stuff already in buffer, so add to it first, then flush */
if (ctx->obuf_len != 0) {
if (i > 0) {
memcpy(&ctx->obuf[ctx->obuf_off + ctx->obuf_len], in, i);
in += i;
inl -= i;
num += i;
ctx->obuf_len += i;
}
/* we now have a full buffer needing flushing */
for (;;) {
i = BIO_write(b->next_bio, &ctx->obuf[ctx->obuf_off], ctx->obuf_len);
if (i <= 0) {
BIO_copy_next_retry(b);
if (i < 0) {
return (num > 0) ? num : i;
}
return num;
}
ctx->obuf_off += i;
ctx->obuf_len -= i;
if (ctx->obuf_len == 0) {
break;
}
}
}
/* we only get here if the buffer has been flushed and we
* still have stuff to write */
ctx->obuf_off = 0;
/* we now have inl bytes to write */
while (inl >= ctx->obuf_size) {
i = BIO_write(b->next_bio, in, inl);
if (i <= 0) {
BIO_copy_next_retry(b);
if (i < 0) {
return (num > 0) ? num : i;
}
return num;
}
num += i;
in += i;
inl -= i;
if (inl == 0) {
return num;
}
}
/* copy the rest into the buffer since we have only a small
* amount left */
}
}
static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) {
BIO_F_BUFFER_CTX *ctx;
long ret = 1;
char *p1, *p2;
int r, *ip;
int ibs, obs;
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
ctx->ibuf_off = 0;
ctx->ibuf_len = 0;
ctx->obuf_off = 0;
ctx->obuf_len = 0;
if (b->next_bio == NULL) {
return 0;
}
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
break;
case BIO_CTRL_INFO:
ret = ctx->obuf_len;
break;
case BIO_CTRL_WPENDING:
ret = (long)ctx->obuf_len;
if (ret == 0) {
if (b->next_bio == NULL) {
return 0;
}
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
}
break;
case BIO_CTRL_PENDING:
ret = (long)ctx->ibuf_len;
if (ret == 0) {
if (b->next_bio == NULL) {
return 0;
}
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
}
break;
case BIO_C_SET_BUFF_SIZE:
ip = (int *)ptr;
if (*ip == 0) {
ibs = (int)num;
obs = ctx->obuf_size;
} else /* if (*ip == 1) */ {
ibs = ctx->ibuf_size;
obs = (int)num;
}
p1 = ctx->ibuf;
p2 = ctx->obuf;
if (ibs > DEFAULT_BUFFER_SIZE && ibs != ctx->ibuf_size) {
p1 = (char *)OPENSSL_malloc(ibs);
if (p1 == NULL) {
goto malloc_error;
}
}
if (obs > DEFAULT_BUFFER_SIZE && obs != ctx->obuf_size) {
p2 = (char *)OPENSSL_malloc(obs);
if (p2 == NULL) {
if (p1 != ctx->ibuf) {
OPENSSL_free(p1);
}
goto malloc_error;
}
}
if (ctx->ibuf != p1) {
OPENSSL_free(ctx->ibuf);
ctx->ibuf = p1;
ctx->ibuf_size = ibs;
}
ctx->ibuf_off = 0;
ctx->ibuf_len = 0;
if (ctx->obuf != p2) {
OPENSSL_free(ctx->obuf);
ctx->obuf = p2;
ctx->obuf_size = obs;
}
ctx->obuf_off = 0;
ctx->obuf_len = 0;
break;
case BIO_CTRL_FLUSH:
if (b->next_bio == NULL) {
return 0;
}
while (ctx->obuf_len > 0) {
BIO_clear_retry_flags(b);
r = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]),
ctx->obuf_len);
BIO_copy_next_retry(b);
if (r <= 0) {
return r;
}
ctx->obuf_off += r;
ctx->obuf_len -= r;
}
ctx->obuf_len = 0;
ctx->obuf_off = 0;
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
break;
default:
if (b->next_bio == NULL) {
return 0;
}
BIO_clear_retry_flags(b);
ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
BIO_copy_next_retry(b);
break;
}
return ret;
malloc_error:
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
static long buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb fp) {
long ret = 1;
if (b->next_bio == NULL) {
return 0;
}
switch (cmd) {
default:
ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
break;
}
return ret;
}
static int buffer_gets(BIO *b, char *buf, int size) {
BIO_F_BUFFER_CTX *ctx;
int num = 0, i, flag;
char *p;
ctx = (BIO_F_BUFFER_CTX *)b->ptr;
if (buf == NULL || size <= 0) {
return 0;
}
size--; /* reserve space for a '\0' */
BIO_clear_retry_flags(b);
for (;;) {
if (ctx->ibuf_len > 0) {
p = &ctx->ibuf[ctx->ibuf_off];
flag = 0;
for (i = 0; (i < ctx->ibuf_len) && (i < size); i++) {
*(buf++) = p[i];
if (p[i] == '\n') {
flag = 1;
i++;
break;
}
}
num += i;
size -= i;
ctx->ibuf_len -= i;
ctx->ibuf_off += i;
if (flag || size == 0) {
*buf = '\0';
return num;
}
} else /* read another chunk */
{
i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size);
if (i <= 0) {
BIO_copy_next_retry(b);
*buf = '\0';
if (i < 0) {
return (num > 0) ? num : i;
}
return num;
}
ctx->ibuf_len = i;
ctx->ibuf_off = 0;
}
}
}
static int buffer_puts(BIO *b, const char *str) {
return buffer_write(b, str, strlen(str));
}
static const BIO_METHOD methods_buffer = {
BIO_TYPE_BUFFER, "buffer", buffer_write, buffer_read,
buffer_puts, buffer_gets, buffer_ctrl, buffer_new,
buffer_free, buffer_callback_ctrl,
};
const BIO_METHOD *BIO_f_buffer(void) { return &methods_buffer; }
int BIO_set_read_buffer_size(BIO *bio, int buffer_size) {
return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 0);
}
int BIO_set_write_buffer_size(BIO *bio, int buffer_size) {
return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 1);
}

View File

@ -0,0 +1,538 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#if !defined(OPENSSL_WINDOWS)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#else
#pragma warning(push, 3)
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma warning(pop)
#endif
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "internal.h"
enum {
BIO_CONN_S_BEFORE,
BIO_CONN_S_BLOCKED_CONNECT,
BIO_CONN_S_OK,
};
typedef struct bio_connect_st {
int state;
char *param_hostname;
char *param_port;
int nbio;
uint8_t ip[4];
unsigned short port;
struct sockaddr_storage them;
socklen_t them_length;
/* the file descriptor is kept in bio->num in order to match the socket
* BIO. */
/* info_callback is called when the connection is initially made
* callback(BIO,state,ret); The callback should return 'ret', state is for
* compatibility with the SSL info_callback. */
int (*info_callback)(const BIO *bio, int state, int ret);
} BIO_CONNECT;
#if !defined(OPENSSL_WINDOWS)
static int closesocket(int sock) {
return close(sock);
}
#endif
/* maybe_copy_ipv4_address sets |*ipv4| to the IPv4 address from |ss| (in
* big-endian order), if |ss| contains an IPv4 socket address. */
static void maybe_copy_ipv4_address(uint8_t *ipv4,
const struct sockaddr_storage *ss) {
const struct sockaddr_in *sin;
if (ss->ss_family != AF_INET) {
return;
}
sin = (const struct sockaddr_in*) ss;
memcpy(ipv4, &sin->sin_addr, 4);
}
static int conn_state(BIO *bio, BIO_CONNECT *c) {
int ret = -1, i;
char *p, *q;
int (*cb)(const BIO *, int, int) = NULL;
if (c->info_callback != NULL) {
cb = c->info_callback;
}
for (;;) {
switch (c->state) {
case BIO_CONN_S_BEFORE:
p = c->param_hostname;
if (p == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_HOSTNAME_SPECIFIED);
goto exit_loop;
}
for (; *p != 0; p++) {
if (*p == ':' || *p == '/') {
break;
}
}
i = *p;
if (i == ':' || i == '/') {
*(p++) = 0;
if (i == ':') {
for (q = p; *q; q++) {
if (*q == '/') {
*q = 0;
break;
}
}
OPENSSL_free(c->param_port);
c->param_port = BUF_strdup(p);
}
}
if (c->param_port == NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_PORT_SPECIFIED);
ERR_add_error_data(2, "host=", c->param_hostname);
goto exit_loop;
}
if (!bio_ip_and_port_to_socket_and_addr(
&bio->num, &c->them, &c->them_length, c->param_hostname,
c->param_port)) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
goto exit_loop;
}
memset(c->ip, 0, 4);
maybe_copy_ipv4_address(c->ip, &c->them);
if (c->nbio) {
if (!bio_socket_nbio(bio->num, 1)) {
OPENSSL_PUT_ERROR(BIO, BIO_R_ERROR_SETTING_NBIO);
ERR_add_error_data(4, "host=", c->param_hostname, ":",
c->param_port);
goto exit_loop;
}
}
i = 1;
ret = setsockopt(bio->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i,
sizeof(i));
if (ret < 0) {
OPENSSL_PUT_SYSTEM_ERROR(setsockopt);
OPENSSL_PUT_ERROR(BIO, BIO_R_KEEPALIVE);
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
goto exit_loop;
}
BIO_clear_retry_flags(bio);
ret = connect(bio->num, (struct sockaddr*) &c->them, c->them_length);
if (ret < 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY));
c->state = BIO_CONN_S_BLOCKED_CONNECT;
bio->retry_reason = BIO_RR_CONNECT;
} else {
OPENSSL_PUT_SYSTEM_ERROR(connect);
OPENSSL_PUT_ERROR(BIO, BIO_R_CONNECT_ERROR);
ERR_add_error_data(4, "host=", c->param_hostname, ":",
c->param_port);
}
goto exit_loop;
} else {
c->state = BIO_CONN_S_OK;
}
break;
case BIO_CONN_S_BLOCKED_CONNECT:
i = bio_sock_error(bio->num);
if (i) {
if (bio_fd_should_retry(ret)) {
BIO_set_flags(bio, (BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY));
c->state = BIO_CONN_S_BLOCKED_CONNECT;
bio->retry_reason = BIO_RR_CONNECT;
ret = -1;
} else {
BIO_clear_retry_flags(bio);
OPENSSL_PUT_SYSTEM_ERROR(connect);
OPENSSL_PUT_ERROR(BIO, BIO_R_NBIO_CONNECT_ERROR);
ERR_add_error_data(4, "host=", c->param_hostname, ":", c->param_port);
ret = 0;
}
goto exit_loop;
} else {
c->state = BIO_CONN_S_OK;
}
break;
case BIO_CONN_S_OK:
ret = 1;
goto exit_loop;
default:
assert(0);
goto exit_loop;
}
if (cb != NULL) {
ret = cb((BIO *)bio, c->state, ret);
if (ret == 0) {
goto end;
}
}
}
exit_loop:
if (cb != NULL) {
ret = cb((BIO *)bio, c->state, ret);
}
end:
return ret;
}
static BIO_CONNECT *BIO_CONNECT_new(void) {
BIO_CONNECT *ret = OPENSSL_malloc(sizeof(BIO_CONNECT));
if (ret == NULL) {
return NULL;
}
memset(ret, 0, sizeof(BIO_CONNECT));
ret->state = BIO_CONN_S_BEFORE;
return ret;
}
static void BIO_CONNECT_free(BIO_CONNECT *c) {
if (c == NULL) {
return;
}
OPENSSL_free(c->param_hostname);
OPENSSL_free(c->param_port);
OPENSSL_free(c);
}
static int conn_new(BIO *bio) {
bio->init = 0;
bio->num = -1;
bio->flags = 0;
bio->ptr = (char *)BIO_CONNECT_new();
return bio->ptr != NULL;
}
static void conn_close_socket(BIO *bio) {
BIO_CONNECT *c = (BIO_CONNECT *) bio->ptr;
if (bio->num == -1) {
return;
}
/* Only do a shutdown if things were established */
if (c->state == BIO_CONN_S_OK) {
shutdown(bio->num, 2);
}
closesocket(bio->num);
bio->num = -1;
}
static int conn_free(BIO *bio) {
if (bio == NULL) {
return 0;
}
if (bio->shutdown) {
conn_close_socket(bio);
}
BIO_CONNECT_free((BIO_CONNECT*) bio->ptr);
return 1;
}
static int conn_read(BIO *bio, char *out, int out_len) {
int ret = 0;
BIO_CONNECT *data;
data = (BIO_CONNECT *)bio->ptr;
if (data->state != BIO_CONN_S_OK) {
ret = conn_state(bio, data);
if (ret <= 0) {
return ret;
}
}
bio_clear_socket_error();
ret = recv(bio->num, out, out_len, 0);
BIO_clear_retry_flags(bio);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_retry_read(bio);
}
}
return ret;
}
static int conn_write(BIO *bio, const char *in, int in_len) {
int ret;
BIO_CONNECT *data;
data = (BIO_CONNECT *)bio->ptr;
if (data->state != BIO_CONN_S_OK) {
ret = conn_state(bio, data);
if (ret <= 0) {
return ret;
}
}
bio_clear_socket_error();
ret = send(bio->num, in, in_len, 0);
BIO_clear_retry_flags(bio);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_retry_write(bio);
}
}
return ret;
}
static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
int *ip;
const char **pptr;
long ret = 1;
BIO_CONNECT *data;
data = (BIO_CONNECT *)bio->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
ret = 0;
data->state = BIO_CONN_S_BEFORE;
conn_close_socket(bio);
bio->flags = 0;
break;
case BIO_C_DO_STATE_MACHINE:
/* use this one to start the connection */
if (data->state != BIO_CONN_S_OK) {
ret = (long)conn_state(bio, data);
} else {
ret = 1;
}
break;
case BIO_C_GET_CONNECT:
/* TODO(fork): can this be removed? (Or maybe this whole file). */
if (ptr != NULL) {
pptr = (const char **)ptr;
if (num == 0) {
*pptr = data->param_hostname;
} else if (num == 1) {
*pptr = data->param_port;
} else if (num == 2) {
*pptr = (char *) &data->ip[0];
} else if (num == 3) {
*((int *)ptr) = data->port;
}
if (!bio->init) {
*pptr = "not initialized";
}
ret = 1;
}
break;
case BIO_C_SET_CONNECT:
if (ptr != NULL) {
bio->init = 1;
if (num == 0) {
OPENSSL_free(data->param_hostname);
data->param_hostname = BUF_strdup(ptr);
if (data->param_hostname == NULL) {
ret = 0;
}
} else if (num == 1) {
OPENSSL_free(data->param_port);
data->param_port = BUF_strdup(ptr);
if (data->param_port == NULL) {
ret = 0;
}
} else {
ret = 0;
}
}
break;
case BIO_C_SET_NBIO:
data->nbio = (int)num;
break;
case BIO_C_GET_FD:
if (bio->init) {
ip = (int *)ptr;
if (ip != NULL) {
*ip = bio->num;
}
ret = 1;
} else {
ret = 0;
}
break;
case BIO_CTRL_GET_CLOSE:
ret = bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
break;
case BIO_CTRL_PENDING:
case BIO_CTRL_WPENDING:
ret = 0;
break;
case BIO_CTRL_FLUSH:
break;
case BIO_CTRL_SET_CALLBACK: {
#if 0 /* FIXME: Should this be used? -- Richard Levitte */
OPENSSL_PUT_ERROR(BIO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
ret = -1;
#else
ret = 0;
#endif
} break;
case BIO_CTRL_GET_CALLBACK: {
int (**fptr)(const BIO *bio, int state, int xret);
fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
*fptr = data->info_callback;
} break;
default:
ret = 0;
break;
}
return (ret);
}
static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
long ret = 1;
BIO_CONNECT *data;
data = (BIO_CONNECT *)bio->ptr;
switch (cmd) {
case BIO_CTRL_SET_CALLBACK: {
data->info_callback = (int (*)(const struct bio_st *, int, int))fp;
} break;
default:
ret = 0;
break;
}
return ret;
}
static int conn_puts(BIO *bp, const char *str) {
return conn_write(bp, str, strlen(str));
}
BIO *BIO_new_connect(const char *hostname) {
BIO *ret;
ret = BIO_new(BIO_s_connect());
if (ret == NULL) {
return NULL;
}
if (!BIO_set_conn_hostname(ret, hostname)) {
BIO_free(ret);
return NULL;
}
return ret;
}
static const BIO_METHOD methods_connectp = {
BIO_TYPE_CONNECT, "socket connect", conn_write, conn_read,
conn_puts, NULL /* connect_gets, */, conn_ctrl, conn_new,
conn_free, conn_callback_ctrl,
};
const BIO_METHOD *BIO_s_connect(void) { return &methods_connectp; }
int BIO_set_conn_hostname(BIO *bio, const char *name) {
return BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, (void*) name);
}
int BIO_set_conn_port(BIO *bio, const char *port_str) {
return BIO_ctrl(bio, BIO_C_SET_CONNECT, 1, (void*) port_str);
}
int BIO_set_nbio(BIO *bio, int on) {
return BIO_ctrl(bio, BIO_C_SET_NBIO, on, NULL);
}

View File

@ -0,0 +1,270 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <errno.h>
#include <string.h>
#if !defined(OPENSSL_WINDOWS)
#include <unistd.h>
#else
#include <io.h>
#pragma warning(push, 3)
#include <windows.h>
#pragma warning(pop)
#endif
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
static int bio_fd_non_fatal_error(int err) {
if (
#ifdef EWOULDBLOCK
err == EWOULDBLOCK ||
#endif
#ifdef WSAEWOULDBLOCK
err == WSAEWOULDBLOCK ||
#endif
#ifdef ENOTCONN
err == ENOTCONN ||
#endif
#ifdef EINTR
err == EINTR ||
#endif
#ifdef EAGAIN
err == EAGAIN ||
#endif
#ifdef EPROTO
err == EPROTO ||
#endif
#ifdef EINPROGRESS
err == EINPROGRESS ||
#endif
#ifdef EALREADY
err == EALREADY ||
#endif
0) {
return 1;
}
return 0;
}
#if defined(OPENSSL_WINDOWS)
int bio_fd_should_retry(int i) {
if (i == -1) {
return bio_fd_non_fatal_error((int)GetLastError());
}
return 0;
}
#else
int bio_fd_should_retry(int i) {
if (i == -1) {
return bio_fd_non_fatal_error(errno);
}
return 0;
}
#endif
BIO *BIO_new_fd(int fd, int close_flag) {
BIO *ret = BIO_new(BIO_s_fd());
if (ret == NULL) {
return NULL;
}
BIO_set_fd(ret, fd, close_flag);
return ret;
}
static int fd_new(BIO *bio) {
/* num is used to store the file descriptor. */
bio->num = -1;
return 1;
}
static int fd_free(BIO *bio) {
if (bio == NULL) {
return 0;
}
if (bio->shutdown) {
if (bio->init) {
close(bio->num);
}
bio->init = 0;
}
return 1;
}
static int fd_read(BIO *b, char *out, int outl) {
int ret = 0;
ret = read(b->num, out, outl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_retry_read(b);
}
}
return ret;
}
static int fd_write(BIO *b, const char *in, int inl) {
int ret = write(b->num, in, inl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_retry_write(b);
}
}
return ret;
}
static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) {
long ret = 1;
int *ip;
switch (cmd) {
case BIO_CTRL_RESET:
num = 0;
case BIO_C_FILE_SEEK:
ret = 0;
if (b->init) {
ret = (long)lseek(b->num, num, SEEK_SET);
}
break;
case BIO_C_FILE_TELL:
case BIO_CTRL_INFO:
ret = 0;
if (b->init) {
ret = (long)lseek(b->num, 0, SEEK_CUR);
}
break;
case BIO_C_SET_FD:
fd_free(b);
b->num = *((int *)ptr);
b->shutdown = (int)num;
b->init = 1;
break;
case BIO_C_GET_FD:
if (b->init) {
ip = (int *)ptr;
if (ip != NULL) {
*ip = b->num;
}
return 1;
} else {
ret = 0;
}
break;
case BIO_CTRL_GET_CLOSE:
ret = b->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
b->shutdown = (int)num;
break;
case BIO_CTRL_PENDING:
case BIO_CTRL_WPENDING:
ret = 0;
break;
case BIO_CTRL_FLUSH:
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
static int fd_puts(BIO *bp, const char *str) {
return fd_write(bp, str, strlen(str));
}
static int fd_gets(BIO *bp, char *buf, int size) {
char *ptr = buf;
char *end = buf + size - 1;
if (size <= 0) {
return 0;
}
while (ptr < end && fd_read(bp, ptr, 1) > 0 && ptr[0] != '\n') {
ptr++;
}
ptr[0] = '\0';
return ptr - buf;
}
static const BIO_METHOD methods_fdp = {
BIO_TYPE_FD, "file descriptor", fd_write, fd_read, fd_puts,
fd_gets, fd_ctrl, fd_new, fd_free, NULL, };
const BIO_METHOD *BIO_s_fd(void) { return &methods_fdp; }
int BIO_set_fd(BIO *bio, int fd, int close_flag) {
return BIO_int_ctrl(bio, BIO_C_SET_FD, close_flag, fd);
}
int BIO_get_fd(BIO *bio, int *out_fd) {
return BIO_ctrl(bio, BIO_C_GET_FD, 0, (char *) out_fd);
}

View File

@ -0,0 +1,350 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#if defined(__linux) || defined(__sun) || defined(__hpux)
/* Following definition aliases fopen to fopen64 on above mentioned
* platforms. This makes it possible to open and sequentially access
* files larger than 2GB from 32-bit application. It does not allow to
* traverse them beyond 2GB with fseek/ftell, but on the other hand *no*
* 32-bit platform permits that, not with fseek/ftell. Not to mention
* that breaking 2GB limit for seeking would require surgery to *our*
* API. But sequential access suffices for practical cases when you
* can run into large files, such as fingerprinting, so we can let API
* alone. For reference, the list of 32-bit platforms which allow for
* sequential access of large files without extra "magic" comprise *BSD,
* Darwin, IRIX...
*/
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#endif
#include <openssl/bio.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#define BIO_FP_READ 0x02
#define BIO_FP_WRITE 0x04
#define BIO_FP_APPEND 0x08
static FILE *open_file(const char *filename, const char *mode) {
#if defined(OPENSSL_WINDOWS) && defined(CP_UTF8)
int sz, len_0 = (int)strlen(filename) + 1;
DWORD flags;
/* Basically there are three cases to cover: a) filename is pure ASCII
* string; b) actual UTF-8 encoded string and c) locale-ized string, i.e. one
* containing 8-bit characters that are meaningful in current system locale.
* If filename is pure ASCII or real UTF-8 encoded string,
* MultiByteToWideChar succeeds and _wfopen works. If filename is locale-ized
* string, chances are that MultiByteToWideChar fails reporting
* ERROR_NO_UNICODE_TRANSLATION, in which case we fall back to fopen... */
if ((sz = MultiByteToWideChar(CP_UTF8, (flags = MB_ERR_INVALID_CHARS),
filename, len_0, NULL, 0)) > 0 ||
(GetLastError() == ERROR_INVALID_FLAGS &&
(sz = MultiByteToWideChar(CP_UTF8, (flags = 0), filename, len_0, NULL,
0)) > 0)) {
WCHAR wmode[8];
WCHAR *wfilename = _alloca(sz * sizeof(WCHAR));
if (MultiByteToWideChar(CP_UTF8, flags, filename, len_0, wfilename, sz) &&
MultiByteToWideChar(CP_UTF8, 0, mode, strlen(mode) + 1, wmode,
sizeof(wmode) / sizeof(wmode[0])) &&
(file = _wfopen(wfilename, wmode)) == NULL &&
(errno == ENOENT ||
errno == EBADF)) /* UTF-8 decode succeeded, but no file, filename
* could still have been locale-ized... */
return fopen(filename, mode);
} else if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) {
return fopen(filename, mode);
}
#else
return fopen(filename, mode);
#endif
}
BIO *BIO_new_file(const char *filename, const char *mode) {
BIO *ret;
FILE *file;
file = open_file(filename, mode);
if (file == NULL) {
OPENSSL_PUT_SYSTEM_ERROR(fopen);
ERR_add_error_data(5, "fopen('", filename, "','", mode, "')");
if (errno == ENOENT) {
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_SUCH_FILE);
} else {
OPENSSL_PUT_ERROR(BIO, BIO_R_SYS_LIB);
}
return NULL;
}
ret = BIO_new(BIO_s_file());
if (ret == NULL) {
fclose(file);
return NULL;
}
BIO_set_fp(ret, file, BIO_CLOSE);
return ret;
}
BIO *BIO_new_fp(FILE *stream, int close_flag) {
BIO *ret = BIO_new(BIO_s_file());
if (ret == NULL) {
return NULL;
}
BIO_set_fp(ret, stream, close_flag);
return ret;
}
static int file_new(BIO *bio) { return 1; }
static int file_free(BIO *bio) {
if (bio == NULL) {
return 0;
}
if (!bio->shutdown) {
return 1;
}
if (bio->init && bio->ptr != NULL) {
fclose(bio->ptr);
bio->ptr = NULL;
}
bio->init = 0;
return 1;
}
static int file_read(BIO *b, char *out, int outl) {
int ret = 0;
if (!b->init) {
return 0;
}
ret = fread(out, 1, outl, (FILE *)b->ptr);
if (ret == 0 && ferror((FILE *)b->ptr)) {
OPENSSL_PUT_SYSTEM_ERROR(fread);
OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB);
ret = -1;
}
return ret;
}
static int file_write(BIO *b, const char *in, int inl) {
int ret = 0;
if (!b->init) {
return 0;
}
ret = fwrite(in, inl, 1, (FILE *)b->ptr);
if (ret > 0) {
ret = inl;
}
return ret;
}
static long file_ctrl(BIO *b, int cmd, long num, void *ptr) {
long ret = 1;
FILE *fp = (FILE *)b->ptr;
FILE **fpp;
char p[4];
switch (cmd) {
case BIO_CTRL_RESET:
num = 0;
case BIO_C_FILE_SEEK:
ret = (long)fseek(fp, num, 0);
break;
case BIO_CTRL_EOF:
ret = (long)feof(fp);
break;
case BIO_C_FILE_TELL:
case BIO_CTRL_INFO:
ret = ftell(fp);
break;
case BIO_C_SET_FILE_PTR:
file_free(b);
b->shutdown = (int)num & BIO_CLOSE;
b->ptr = ptr;
b->init = 1;
break;
case BIO_C_SET_FILENAME:
file_free(b);
b->shutdown = (int)num & BIO_CLOSE;
if (num & BIO_FP_APPEND) {
if (num & BIO_FP_READ) {
BUF_strlcpy(p, "a+", sizeof(p));
} else {
BUF_strlcpy(p, "a", sizeof(p));
}
} else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE)) {
BUF_strlcpy(p, "r+", sizeof(p));
} else if (num & BIO_FP_WRITE) {
BUF_strlcpy(p, "w", sizeof(p));
} else if (num & BIO_FP_READ) {
BUF_strlcpy(p, "r", sizeof(p));
} else {
OPENSSL_PUT_ERROR(BIO, BIO_R_BAD_FOPEN_MODE);
ret = 0;
break;
}
fp = open_file(ptr, p);
if (fp == NULL) {
OPENSSL_PUT_SYSTEM_ERROR(fopen);
ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
OPENSSL_PUT_ERROR(BIO, ERR_R_SYS_LIB);
ret = 0;
break;
}
b->ptr = fp;
b->init = 1;
break;
case BIO_C_GET_FILE_PTR:
/* the ptr parameter is actually a FILE ** in this case. */
if (ptr != NULL) {
fpp = (FILE **)ptr;
*fpp = (FILE *)b->ptr;
}
break;
case BIO_CTRL_GET_CLOSE:
ret = (long)b->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
b->shutdown = (int)num;
break;
case BIO_CTRL_FLUSH:
ret = 0 == fflush((FILE *)b->ptr);
break;
case BIO_CTRL_WPENDING:
case BIO_CTRL_PENDING:
default:
ret = 0;
break;
}
return ret;
}
static int file_gets(BIO *bp, char *buf, int size) {
int ret = 0;
if (size == 0) {
return 0;
}
if (!fgets(buf, size, (FILE *)bp->ptr)) {
buf[0] = 0;
goto err;
}
ret = strlen(buf);
err:
return ret;
}
static int file_puts(BIO *bp, const char *str) {
return file_write(bp, str, strlen(str));
}
static const BIO_METHOD methods_filep = {
BIO_TYPE_FILE, "FILE pointer", file_write, file_read, file_puts,
file_gets, file_ctrl, file_new, file_free, NULL, };
const BIO_METHOD *BIO_s_file(void) { return &methods_filep; }
int BIO_get_fp(BIO *bio, FILE **out_file) {
return BIO_ctrl(bio, BIO_C_GET_FILE_PTR, 0, (char*) out_file);
}
int BIO_set_fp(BIO *bio, FILE *file, int close_flag) {
return BIO_ctrl(bio, BIO_C_SET_FILE_PTR, close_flag, (char *) file);
}
int BIO_read_filename(BIO *bio, const char *filename) {
return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_READ,
(char *)filename);
}
int BIO_write_filename(BIO *bio, const char *filename) {
return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_WRITE,
(char *)filename);
}
int BIO_append_filename(BIO *bio, const char *filename) {
return BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE | BIO_FP_APPEND,
(char *)filename);
}
int BIO_rw_filename(BIO *bio, const char *filename) {
return BIO_ctrl(bio, BIO_C_SET_FILENAME,
BIO_CLOSE | BIO_FP_READ | BIO_FP_WRITE, (char *)filename);
}

View File

@ -0,0 +1,192 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <limits.h>
#include <string.h>
/* hexdump_ctx contains the state of a hexdump. */
struct hexdump_ctx {
BIO *bio;
char right_chars[18]; /* the contents of the right-hand side, ASCII dump. */
unsigned used; /* number of bytes in the current line. */
size_t n; /* number of bytes total. */
unsigned indent;
};
static void hexbyte(char *out, uint8_t b) {
static const char hextable[] = "0123456789abcdef";
out[0] = hextable[b>>4];
out[1] = hextable[b&0x0f];
}
static char to_char(uint8_t b) {
if (b < 32 || b > 126) {
return '.';
}
return b;
}
/* hexdump_write adds |len| bytes of |data| to the current hex dump described by
* |ctx|. */
static int hexdump_write(struct hexdump_ctx *ctx, const uint8_t *data,
size_t len) {
size_t i;
char buf[10];
unsigned l;
/* Output lines look like:
* 00000010 2e 2f 30 31 32 33 34 35 36 37 38 ... 3c 3d // |./0123456789:;<=|
* ^ offset ^ extra space ^ ASCII of line
*/
for (i = 0; i < len; i++) {
if (ctx->used == 0) {
/* The beginning of a line. */
BIO_indent(ctx->bio, ctx->indent, UINT_MAX);
hexbyte(&buf[0], ctx->n >> 24);
hexbyte(&buf[2], ctx->n >> 16);
hexbyte(&buf[4], ctx->n >> 8);
hexbyte(&buf[6], ctx->n);
buf[8] = buf[9] = ' ';
if (BIO_write(ctx->bio, buf, 10) < 0) {
return 0;
}
}
hexbyte(buf, data[i]);
buf[2] = ' ';
l = 3;
if (ctx->used == 7) {
/* There's an additional space after the 8th byte. */
buf[3] = ' ';
l = 4;
} else if (ctx->used == 15) {
/* At the end of the line there's an extra space and the bar for the
* right column. */
buf[3] = ' ';
buf[4] = '|';
l = 5;
}
if (BIO_write(ctx->bio, buf, l) < 0) {
return 0;
}
ctx->right_chars[ctx->used] = to_char(data[i]);
ctx->used++;
ctx->n++;
if (ctx->used == 16) {
ctx->right_chars[16] = '|';
ctx->right_chars[17] = '\n';
if (BIO_write(ctx->bio, ctx->right_chars, sizeof(ctx->right_chars)) < 0) {
return 0;
}
ctx->used = 0;
}
}
return 1;
}
/* finish flushes any buffered data in |ctx|. */
static int finish(struct hexdump_ctx *ctx) {
/* See the comments in |hexdump| for the details of this format. */
const unsigned n_bytes = ctx->used;
unsigned l;
char buf[5];
if (n_bytes == 0) {
return 1;
}
memset(buf, ' ', 4);
buf[4] = '|';
for (; ctx->used < 16; ctx->used++) {
l = 3;
if (ctx->used == 7) {
l = 4;
} else if (ctx->used == 15) {
l = 5;
}
if (BIO_write(ctx->bio, buf, l) < 0) {
return 0;
}
}
ctx->right_chars[n_bytes] = '|';
ctx->right_chars[n_bytes + 1] = '\n';
if (BIO_write(ctx->bio, ctx->right_chars, n_bytes + 2) < 0) {
return 0;
}
return 1;
}
int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len, unsigned indent) {
struct hexdump_ctx ctx;
memset(&ctx, 0, sizeof(ctx));
ctx.bio = bio;
ctx.indent = indent;
if (!hexdump_write(&ctx, data, len) || !finish(&ctx)) {
return 0;
}
return 1;
}

View File

@ -0,0 +1,108 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#ifndef OPENSSL_HEADER_BIO_INTERNAL_H
#define OPENSSL_HEADER_BIO_INTERNAL_H
#include <openssl/base.h>
#if !defined(OPENSSL_WINDOWS)
#if defined(OPENSSL_PNACL)
/* newlib uses u_short in socket.h without defining it. */
typedef unsigned short u_short;
#endif
#include <sys/types.h>
#include <sys/socket.h>
#else
typedef int socklen_t;
#endif
#if defined(__cplusplus)
extern "C" {
#endif
/* BIO_ip_and_port_to_socket_and_addr creates a socket and fills in |*out_addr|
* and |*out_addr_length| with the correct values for connecting to |hostname|
* on |port_str|. It returns one on success or zero on error. */
int bio_ip_and_port_to_socket_and_addr(int *out_sock,
struct sockaddr_storage *out_addr,
socklen_t *out_addr_length,
const char *hostname,
const char *port_str);
/* BIO_socket_nbio sets whether |sock| is non-blocking. It returns one on
* success and zero otherwise. */
int bio_socket_nbio(int sock, int on);
/* BIO_clear_socket_error clears the last system socket error.
*
* TODO(fork): remove all callers of this. */
void bio_clear_socket_error(void);
/* BIO_sock_error returns the last socket error on |sock|. */
int bio_sock_error(int sock);
/* BIO_fd_should_retry returns non-zero if |return_value| indicates an error
* and |errno| indicates that it's non-fatal. */
int bio_fd_should_retry(int return_value);
#if defined(__cplusplus)
} /* extern C */
#endif
#endif /* OPENSSL_HEADER_BIO_INTERNAL_H */

View File

@ -0,0 +1,803 @@
/* ====================================================================
* Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#include <openssl/bio.h>
#include <assert.h>
#include <string.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
struct bio_bio_st {
BIO *peer; /* NULL if buf == NULL.
* If peer != NULL, then peer->ptr is also a bio_bio_st,
* and its "peer" member points back to us.
* peer != NULL iff init != 0 in the BIO. */
/* This is for what we write (i.e. reading uses peer's struct): */
int closed; /* valid iff peer != NULL */
size_t len; /* valid iff buf != NULL; 0 if peer == NULL */
size_t offset; /* valid iff buf != NULL; 0 if len == 0 */
size_t size;
uint8_t *buf; /* "size" elements (if != NULL) */
char buf_externally_allocated; /* true iff buf was externally allocated. */
char zero_copy_read_lock; /* true iff a zero copy read operation
* is in progress. */
char zero_copy_write_lock; /* true iff a zero copy write operation
* is in progress. */
size_t request; /* valid iff peer != NULL; 0 if len != 0,
* otherwise set by peer to number of bytes
* it (unsuccessfully) tried to read,
* never more than buffer space (size-len) warrants. */
};
static int bio_new(BIO *bio) {
struct bio_bio_st *b;
b = OPENSSL_malloc(sizeof *b);
if (b == NULL) {
return 0;
}
memset(b, 0, sizeof(struct bio_bio_st));
b->size = 17 * 1024; /* enough for one TLS record (just a default) */
bio->ptr = b;
return 1;
}
static void bio_destroy_pair(BIO *bio) {
struct bio_bio_st *b = bio->ptr;
BIO *peer_bio;
struct bio_bio_st *peer_b;
if (b == NULL) {
return;
}
peer_bio = b->peer;
if (peer_bio == NULL) {
return;
}
peer_b = peer_bio->ptr;
assert(peer_b != NULL);
assert(peer_b->peer == bio);
peer_b->peer = NULL;
peer_bio->init = 0;
assert(peer_b->buf != NULL);
peer_b->len = 0;
peer_b->offset = 0;
b->peer = NULL;
bio->init = 0;
assert(b->buf != NULL);
b->len = 0;
b->offset = 0;
}
static int bio_free(BIO *bio) {
struct bio_bio_st *b;
if (bio == NULL) {
return 0;
}
b = bio->ptr;
assert(b != NULL);
if (b->peer) {
bio_destroy_pair(bio);
}
if (!b->buf_externally_allocated) {
OPENSSL_free(b->buf);
}
OPENSSL_free(b);
return 1;
}
static size_t bio_zero_copy_get_read_buf(struct bio_bio_st* peer_b,
uint8_t** out_read_buf,
size_t* out_buf_offset) {
size_t max_available;
if (peer_b->len > peer_b->size - peer_b->offset) {
/* Only the first half of the ring buffer can be read. */
max_available = peer_b->size - peer_b->offset;
} else {
max_available = peer_b->len;
}
*out_read_buf = peer_b->buf;
*out_buf_offset = peer_b->offset;
return max_available;
}
int BIO_zero_copy_get_read_buf(BIO* bio, uint8_t** out_read_buf,
size_t* out_buf_offset,
size_t* out_available_bytes) {
struct bio_bio_st* b;
struct bio_bio_st* peer_b;
size_t max_available;
*out_available_bytes = 0;
BIO_clear_retry_flags(bio);
if (!bio->init) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
return 0;
}
b = bio->ptr;
if (!b || !b->peer) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return 0;
}
peer_b = b->peer->ptr;
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return 0;
}
if (peer_b->zero_copy_read_lock) {
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
return 0;
}
peer_b->request = 0; /* Is not used by zero-copy API. */
max_available =
bio_zero_copy_get_read_buf(peer_b, out_read_buf, out_buf_offset);
assert(peer_b->buf != NULL);
if (max_available > 0) {
peer_b->zero_copy_read_lock = 1;
}
*out_available_bytes = max_available;
return 1;
}
int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) {
struct bio_bio_st* b;
struct bio_bio_st* peer_b;
size_t max_available;
size_t dummy_read_offset;
uint8_t* dummy_read_buf;
assert(BIO_get_retry_flags(bio) == 0);
if (!bio->init) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
return 0;
}
b = bio->ptr;
if (!b || !b->peer) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return 0;
}
peer_b = b->peer->ptr;
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return 0;
}
if (!peer_b->zero_copy_read_lock) {
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
return 0;
}
max_available =
bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset);
if (bytes_read > max_available) {
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
return 0;
}
peer_b->len -= bytes_read;
assert(peer_b->len >= 0);
assert(peer_b->offset + bytes_read <= peer_b->size);
/* Move read offset. If zero_copy_write_lock == 1 we must advance the
* offset even if buffer becomes empty, to make sure
* write_offset = (offset + len) mod size does not change. */
if (peer_b->offset + bytes_read == peer_b->size ||
(!peer_b->zero_copy_write_lock && peer_b->len == 0)) {
peer_b->offset = 0;
} else {
peer_b->offset += bytes_read;
}
bio->num_read += bytes_read;
peer_b->zero_copy_read_lock = 0;
return 1;
}
static size_t bio_zero_copy_get_write_buf(struct bio_bio_st* b,
uint8_t** out_write_buf,
size_t* out_buf_offset) {
size_t write_offset;
size_t max_available;
assert(b->len <= b->size);
write_offset = b->offset + b->len;
if (write_offset >= b->size) {
/* Only the first half of the ring buffer can be written to. */
write_offset -= b->size;
/* write up to the start of the ring buffer. */
max_available = b->offset - write_offset;
} else {
/* write up to the end the buffer. */
max_available = b->size - write_offset;
}
*out_write_buf = b->buf;
*out_buf_offset = write_offset;
return max_available;
}
int BIO_zero_copy_get_write_buf(BIO* bio, uint8_t** out_write_buf,
size_t* out_buf_offset,
size_t* out_available_bytes) {
struct bio_bio_st* b;
struct bio_bio_st* peer_b;
size_t max_available;
*out_available_bytes = 0;
BIO_clear_retry_flags(bio);
if (!bio->init) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
return 0;
}
b = bio->ptr;
if (!b || !b->buf || !b->peer) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return 0;
}
peer_b = b->peer->ptr;
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return 0;
}
assert(b->buf != NULL);
if (b->zero_copy_write_lock) {
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
return 0;
}
b->request = 0;
if (b->closed) {
/* Bio is already closed. */
OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
return 0;
}
max_available = bio_zero_copy_get_write_buf(b, out_write_buf, out_buf_offset);
if (max_available > 0) {
b->zero_copy_write_lock = 1;
}
*out_available_bytes = max_available;
return 1;
}
int BIO_zero_copy_get_write_buf_done(BIO* bio, size_t bytes_written) {
struct bio_bio_st* b;
struct bio_bio_st* peer_b;
size_t rest;
size_t dummy_write_offset;
uint8_t* dummy_write_buf;
if (!bio->init) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
return 0;
}
b = bio->ptr;
if (!b || !b->buf || !b->peer) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return 0;
}
peer_b = b->peer->ptr;
if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
return 0;
}
b->request = 0;
if (b->closed) {
/* BIO is already closed. */
OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
return 0;
}
if (!b->zero_copy_write_lock) {
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
return 0;
}
rest = bio_zero_copy_get_write_buf(b, &dummy_write_buf, &dummy_write_offset);
if (bytes_written > rest) {
OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
return 0;
}
bio->num_write += bytes_written;
/* Move write offset. */
b->len += bytes_written;
b->zero_copy_write_lock = 0;
return 1;
}
static int bio_read(BIO *bio, char *buf, int size_) {
size_t size = size_;
size_t rest;
struct bio_bio_st *b, *peer_b;
BIO_clear_retry_flags(bio);
if (!bio->init) {
return 0;
}
b = bio->ptr;
assert(b != NULL);
assert(b->peer != NULL);
peer_b = b->peer->ptr;
assert(peer_b != NULL);
assert(peer_b->buf != NULL);
peer_b->request = 0; /* will be set in "retry_read" situation */
if (buf == NULL || size == 0 || peer_b->zero_copy_read_lock) {
return 0;
}
if (peer_b->len == 0) {
if (peer_b->closed) {
return 0; /* writer has closed, and no data is left */
} else {
BIO_set_retry_read(bio); /* buffer is empty */
if (size <= peer_b->size) {
peer_b->request = size;
} else {
/* don't ask for more than the peer can
* deliver in one write */
peer_b->request = peer_b->size;
}
return -1;
}
}
/* we can read */
if (peer_b->len < size) {
size = peer_b->len;
}
/* now read "size" bytes */
rest = size;
assert(rest > 0);
/* one or two iterations */
do {
size_t chunk;
assert(rest <= peer_b->len);
if (peer_b->offset + rest <= peer_b->size) {
chunk = rest;
} else {
/* wrap around ring buffer */
chunk = peer_b->size - peer_b->offset;
}
assert(peer_b->offset + chunk <= peer_b->size);
memcpy(buf, peer_b->buf + peer_b->offset, chunk);
peer_b->len -= chunk;
/* If zero_copy_write_lock == 1 we must advance the offset even if buffer
* becomes empty, to make sure write_offset = (offset + len) % size
* does not change. */
if (peer_b->len || peer_b->zero_copy_write_lock) {
peer_b->offset += chunk;
assert(peer_b->offset <= peer_b->size);
if (peer_b->offset == peer_b->size) {
peer_b->offset = 0;
}
buf += chunk;
} else {
/* buffer now empty, no need to advance "buf" */
assert(chunk == rest);
peer_b->offset = 0;
}
rest -= chunk;
} while (rest);
return size;
}
static int bio_write(BIO *bio, const char *buf, int num_) {
size_t num = num_;
size_t rest;
struct bio_bio_st *b;
BIO_clear_retry_flags(bio);
if (!bio->init || buf == NULL || num == 0) {
return 0;
}
b = bio->ptr;
assert(b != NULL);
assert(b->peer != NULL);
assert(b->buf != NULL);
if (b->zero_copy_write_lock) {
return 0;
}
b->request = 0;
if (b->closed) {
/* we already closed */
OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
return -1;
}
assert(b->len <= b->size);
if (b->len == b->size) {
BIO_set_retry_write(bio); /* buffer is full */
return -1;
}
/* we can write */
if (num > b->size - b->len) {
num = b->size - b->len;
}
/* now write "num" bytes */
rest = num;
assert(rest > 0);
/* one or two iterations */
do {
size_t write_offset;
size_t chunk;
assert(b->len + rest <= b->size);
write_offset = b->offset + b->len;
if (write_offset >= b->size) {
write_offset -= b->size;
}
/* b->buf[write_offset] is the first byte we can write to. */
if (write_offset + rest <= b->size) {
chunk = rest;
} else {
/* wrap around ring buffer */
chunk = b->size - write_offset;
}
memcpy(b->buf + write_offset, buf, chunk);
b->len += chunk;
assert(b->len <= b->size);
rest -= chunk;
buf += chunk;
} while (rest);
return num;
}
static int bio_make_pair(BIO* bio1, BIO* bio2,
size_t writebuf1_len, uint8_t* ext_writebuf1,
size_t writebuf2_len, uint8_t* ext_writebuf2) {
struct bio_bio_st *b1, *b2;
assert(bio1 != NULL);
assert(bio2 != NULL);
b1 = bio1->ptr;
b2 = bio2->ptr;
if (b1->peer != NULL || b2->peer != NULL) {
OPENSSL_PUT_ERROR(BIO, BIO_R_IN_USE);
return 0;
}
assert(b1->buf_externally_allocated == 0);
assert(b2->buf_externally_allocated == 0);
if (b1->buf == NULL) {
if (writebuf1_len) {
b1->size = writebuf1_len;
}
if (!ext_writebuf1) {
b1->buf_externally_allocated = 0;
b1->buf = OPENSSL_malloc(b1->size);
if (b1->buf == NULL) {
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
b1->buf = ext_writebuf1;
b1->buf_externally_allocated = 1;
}
b1->len = 0;
b1->offset = 0;
}
if (b2->buf == NULL) {
if (writebuf2_len) {
b2->size = writebuf2_len;
}
if (!ext_writebuf2) {
b2->buf_externally_allocated = 0;
b2->buf = OPENSSL_malloc(b2->size);
if (b2->buf == NULL) {
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
b2->buf = ext_writebuf2;
b2->buf_externally_allocated = 1;
}
b2->len = 0;
b2->offset = 0;
}
b1->peer = bio2;
b1->closed = 0;
b1->request = 0;
b1->zero_copy_read_lock = 0;
b1->zero_copy_write_lock = 0;
b2->peer = bio1;
b2->closed = 0;
b2->request = 0;
b2->zero_copy_read_lock = 0;
b2->zero_copy_write_lock = 0;
bio1->init = 1;
bio2->init = 1;
return 1;
}
static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
long ret;
struct bio_bio_st *b = bio->ptr;
assert(b != NULL);
switch (cmd) {
/* specific CTRL codes */
case BIO_C_GET_WRITE_BUF_SIZE:
ret = (long)b->size;
break;
case BIO_C_GET_WRITE_GUARANTEE:
/* How many bytes can the caller feed to the next write
* without having to keep any? */
if (b->peer == NULL || b->closed) {
ret = 0;
} else {
ret = (long)b->size - b->len;
}
break;
case BIO_C_GET_READ_REQUEST:
/* If the peer unsuccessfully tried to read, how many bytes
* were requested? (As with BIO_CTRL_PENDING, that number
* can usually be treated as boolean.) */
ret = (long)b->request;
break;
case BIO_C_RESET_READ_REQUEST:
/* Reset request. (Can be useful after read attempts
* at the other side that are meant to be non-blocking,
* e.g. when probing SSL_read to see if any data is
* available.) */
b->request = 0;
ret = 1;
break;
case BIO_C_SHUTDOWN_WR:
/* similar to shutdown(..., SHUT_WR) */
b->closed = 1;
ret = 1;
break;
/* standard CTRL codes follow */
case BIO_CTRL_GET_CLOSE:
ret = bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
ret = 1;
break;
case BIO_CTRL_PENDING:
if (b->peer != NULL) {
struct bio_bio_st *peer_b = b->peer->ptr;
ret = (long)peer_b->len;
} else {
ret = 0;
}
break;
case BIO_CTRL_WPENDING:
ret = 0;
if (b->buf != NULL) {
ret = (long)b->len;
}
break;
case BIO_CTRL_FLUSH:
ret = 1;
break;
case BIO_CTRL_EOF: {
BIO *other_bio = ptr;
if (other_bio) {
struct bio_bio_st *other_b = other_bio->ptr;
assert(other_b != NULL);
ret = other_b->len == 0 && other_b->closed;
} else {
ret = 1;
}
} break;
default:
ret = 0;
}
return ret;
}
static int bio_puts(BIO *bio, const char *str) {
return bio_write(bio, str, strlen(str));
}
static const BIO_METHOD methods_biop = {
BIO_TYPE_BIO, "BIO pair", bio_write, bio_read,
bio_puts, NULL /* no bio_gets */, bio_ctrl, bio_new,
bio_free, NULL /* no bio_callback_ctrl */
};
const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1,
BIO** bio2_p, size_t writebuf2) {
return BIO_new_bio_pair_external_buf(bio1_p, writebuf1, NULL, bio2_p,
writebuf2, NULL);
}
int BIO_new_bio_pair_external_buf(BIO** bio1_p, size_t writebuf1_len,
uint8_t* ext_writebuf1,
BIO** bio2_p, size_t writebuf2_len,
uint8_t* ext_writebuf2) {
BIO *bio1 = NULL, *bio2 = NULL;
int ret = 0;
/* External buffers must have sizes greater than 0. */
if ((ext_writebuf1 && !writebuf1_len) || (ext_writebuf2 && !writebuf2_len)) {
goto err;
}
bio1 = BIO_new(bio_s_bio());
if (bio1 == NULL) {
goto err;
}
bio2 = BIO_new(bio_s_bio());
if (bio2 == NULL) {
goto err;
}
if (!bio_make_pair(bio1, bio2, writebuf1_len, ext_writebuf1, writebuf2_len,
ext_writebuf2)) {
goto err;
}
ret = 1;
err:
if (ret == 0) {
BIO_free(bio1);
bio1 = NULL;
BIO_free(bio2);
bio2 = NULL;
}
*bio1_p = bio1;
*bio2_p = bio2;
return ret;
}
size_t BIO_ctrl_get_read_request(BIO *bio) {
return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
}
size_t BIO_ctrl_get_write_guarantee(BIO *bio) {
return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
}
int BIO_shutdown_wr(BIO *bio) {
return BIO_ctrl(bio, BIO_C_SHUTDOWN_WR, 0, NULL);
}

View File

@ -0,0 +1,115 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#if !defined(_POSIX_C_SOURCE)
#define _POSIX_C_SOURCE 201410L /* for snprintf, vprintf etc */
#endif
#include <openssl/bio.h>
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/mem.h>
int BIO_printf(BIO *bio, const char *format, ...) {
va_list args;
char buf[256], *out, out_malloced = 0;
int out_len, ret;
va_start(args, format);
out_len = vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
#if defined(OPENSSL_WINDOWS)
/* On Windows, vsnprintf returns -1 rather than the requested length on
* truncation */
if (out_len < 0) {
va_start(args, format);
out_len = _vscprintf(format, args);
va_end(args);
assert(out_len >= sizeof(buf));
}
#endif
if (out_len >= sizeof(buf)) {
const int requested_len = out_len;
/* The output was truncated. Note that vsnprintf's return value
* does not include a trailing NUL, but the buffer must be sized
* for it. */
out = OPENSSL_malloc(requested_len + 1);
out_malloced = 1;
if (out == NULL) {
OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
return -1;
}
va_start(args, format);
out_len = vsnprintf(out, requested_len + 1, format, args);
va_end(args);
assert(out_len == requested_len);
} else {
out = buf;
}
ret = BIO_write(bio, out, out_len);
if (out_malloced) {
OPENSSL_free(out);
}
return ret;
}

View File

@ -0,0 +1,195 @@
/* crypto/bio/bss_sock.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bio.h>
#include <fcntl.h>
#include <string.h>
#if !defined(OPENSSL_WINDOWS)
#include <unistd.h>
#else
#pragma warning(push, 3)
#include <winsock2.h>
#pragma warning(pop)
#pragma comment(lib, "Ws2_32.lib")
#endif
#include "internal.h"
#if !defined(OPENSSL_WINDOWS)
static int closesocket(int sock) {
return close(sock);
}
#endif
static int sock_new(BIO *bio) {
bio->init = 0;
bio->num = 0;
bio->ptr = NULL;
bio->flags = 0;
return 1;
}
static int sock_free(BIO *bio) {
if (bio == NULL) {
return 0;
}
if (bio->shutdown) {
if (bio->init) {
closesocket(bio->num);
}
bio->init = 0;
bio->flags = 0;
}
return 1;
}
static int sock_read(BIO *b, char *out, int outl) {
int ret = 0;
if (out == NULL) {
return 0;
}
bio_clear_socket_error();
ret = recv(b->num, out, outl, 0);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_retry_read(b);
}
}
return ret;
}
static int sock_write(BIO *b, const char *in, int inl) {
int ret;
bio_clear_socket_error();
ret = send(b->num, in, inl, 0);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (bio_fd_should_retry(ret)) {
BIO_set_retry_write(b);
}
}
return ret;
}
static int sock_puts(BIO *bp, const char *str) {
return sock_write(bp, str, strlen(str));
}
static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
long ret = 1;
int *ip;
switch (cmd) {
case BIO_C_SET_FD:
sock_free(b);
b->num = *((int *)ptr);
b->shutdown = (int)num;
b->init = 1;
break;
case BIO_C_GET_FD:
if (b->init) {
ip = (int *)ptr;
if (ip != NULL) {
*ip = b->num;
}
ret = b->num;
} else {
ret = -1;
}
break;
case BIO_CTRL_GET_CLOSE:
ret = b->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
b->shutdown = (int)num;
break;
case BIO_CTRL_FLUSH:
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
static const BIO_METHOD methods_sockp = {
BIO_TYPE_SOCKET, "socket", sock_write, sock_read, sock_puts,
NULL /* gets, */, sock_ctrl, sock_new, sock_free, NULL,
};
const BIO_METHOD *BIO_s_socket(void) { return &methods_sockp; }
BIO *BIO_new_socket(int fd, int close_flag) {
BIO *ret;
ret = BIO_new(BIO_s_socket());
if (ret == NULL) {
return NULL;
}
BIO_set_fd(ret, fd, close_flag);
return ret;
}

View File

@ -0,0 +1,113 @@
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#include <openssl/bio.h>
#include <openssl/err.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#if !defined(OPENSSL_WINDOWS)
#include <netdb.h>
#include <unistd.h>
#else
#pragma warning(push, 3)
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma warning(pop)
#endif
#include "internal.h"
int bio_ip_and_port_to_socket_and_addr(int *out_sock,
struct sockaddr_storage *out_addr,
socklen_t *out_addr_length,
const char *hostname,
const char *port_str) {
struct addrinfo hint, *result, *cur;
int ret;
*out_sock = -1;
memset(&hint, 0, sizeof(hint));
hint.ai_family = AF_UNSPEC;
hint.ai_socktype = SOCK_STREAM;
ret = getaddrinfo(hostname, port_str, &hint, &result);
if (ret != 0) {
OPENSSL_PUT_ERROR(SYS, 0);
ERR_add_error_data(1, gai_strerror(ret));
return 0;
}
ret = 0;
for (cur = result; cur; cur = cur->ai_next) {
if (cur->ai_addrlen > sizeof(struct sockaddr_storage)) {
continue;
}
memset(out_addr, 0, sizeof(struct sockaddr_storage));
memcpy(out_addr, cur->ai_addr, cur->ai_addrlen);
*out_addr_length = cur->ai_addrlen;
*out_sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
if (*out_sock < 0) {
OPENSSL_PUT_SYSTEM_ERROR(socket);
goto out;
}
ret = 1;
break;
}
out:
freeaddrinfo(result);
return ret;
}
int bio_socket_nbio(int sock, int on) {
#if defined(OPENSSL_WINDOWS)
u_long arg = on;
return 0 == ioctlsocket(sock, FIONBIO, &arg);
#else
int flags = fcntl(sock, F_GETFL, 0);
if (flags < 0) {
return 0;
}
if (!on) {
flags &= ~O_NONBLOCK;
} else {
flags |= O_NONBLOCK;
}
return fcntl(sock, F_SETFL, flags) == 0;
#endif
}
void bio_clear_socket_error(void) {}
int bio_sock_error(int sock) {
int error;
socklen_t error_size = sizeof(error);
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)&error, &error_size) < 0) {
return 1;
}
return error;
}

View File

@ -0,0 +1,68 @@
include_directories(. .. ../../include)
if (${ARCH} STREQUAL "x86_64")
set(
BN_ARCH_SOURCES
x86_64-mont.${ASM_EXT}
x86_64-mont5.${ASM_EXT}
rsaz-x86_64.${ASM_EXT}
rsaz-avx2.${ASM_EXT}
rsaz_exp.c
)
endif()
if (${ARCH} STREQUAL "x86")
set(
BN_ARCH_SOURCES
bn-586.${ASM_EXT}
co-586.${ASM_EXT}
x86-mont.${ASM_EXT}
)
endif()
if (${ARCH} STREQUAL "arm")
set(
BN_ARCH_SOURCES
armv4-mont.${ASM_EXT}
)
endif()
add_library(
bn
OBJECT
add.c
asm/x86_64-gcc.c
bn.c
bn_asn1.c
cmp.c
convert.c
ctx.c
div.c
exponentiation.c
generic.c
gcd.c
kronecker.c
montgomery.c
mul.c
prime.c
random.c
shift.c
sqrt.c
${BN_ARCH_SOURCES}
)
perlasm(x86_64-mont.${ASM_EXT} asm/x86_64-mont.pl)
perlasm(x86_64-mont5.${ASM_EXT} asm/x86_64-mont5.pl)
perlasm(rsaz-x86_64.${ASM_EXT} asm/rsaz-x86_64.pl)
perlasm(rsaz-avx2.${ASM_EXT} asm/rsaz-avx2.pl)
perlasm(bn-586.${ASM_EXT} asm/bn-586.pl)
perlasm(co-586.${ASM_EXT} asm/co-586.pl)
perlasm(x86-mont.${ASM_EXT} asm/x86-mont.pl)
perlasm(armv4-mont.${ASM_EXT} asm/armv4-mont.pl)

View File

@ -0,0 +1,394 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "internal.h"
int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
const BIGNUM *tmp;
int a_neg = a->neg, ret;
/* a + b a+b
* a + -b a-b
* -a + b b-a
* -a + -b -(a+b)
*/
if (a_neg ^ b->neg) {
/* only one is negative */
if (a_neg) {
tmp = a;
a = b;
b = tmp;
}
/* we are now a - b */
if (BN_ucmp(a, b) < 0) {
if (!BN_usub(r, b, a)) {
return 0;
}
r->neg = 1;
} else {
if (!BN_usub(r, a, b)) {
return 0;
}
r->neg = 0;
}
return 1;
}
ret = BN_uadd(r, a, b);
r->neg = a_neg;
return ret;
}
int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
int max, min, dif;
BN_ULONG *ap, *bp, *rp, carry, t1, t2;
const BIGNUM *tmp;
if (a->top < b->top) {
tmp = a;
a = b;
b = tmp;
}
max = a->top;
min = b->top;
dif = max - min;
if (bn_wexpand(r, max + 1) == NULL) {
return 0;
}
r->top = max;
ap = a->d;
bp = b->d;
rp = r->d;
carry = bn_add_words(rp, ap, bp, min);
rp += min;
ap += min;
bp += min;
if (carry) {
while (dif) {
dif--;
t1 = *(ap++);
t2 = (t1 + 1) & BN_MASK2;
*(rp++) = t2;
if (t2) {
carry = 0;
break;
}
}
if (carry) {
/* carry != 0 => dif == 0 */
*rp = 1;
r->top++;
}
}
if (dif && rp != ap) {
while (dif--) {
/* copy remaining words if ap != rp */
*(rp++) = *(ap++);
}
}
r->neg = 0;
return 1;
}
int BN_add_word(BIGNUM *a, BN_ULONG w) {
BN_ULONG l;
int i;
w &= BN_MASK2;
/* degenerate case: w is zero */
if (!w) {
return 1;
}
/* degenerate case: a is zero */
if (BN_is_zero(a)) {
return BN_set_word(a, w);
}
/* handle 'a' when negative */
if (a->neg) {
a->neg = 0;
i = BN_sub_word(a, w);
if (!BN_is_zero(a)) {
a->neg = !(a->neg);
}
return i;
}
for (i = 0; w != 0 && i < a->top; i++) {
a->d[i] = l = (a->d[i] + w) & BN_MASK2;
w = (w > l) ? 1 : 0;
}
if (w && i == a->top) {
if (bn_wexpand(a, a->top + 1) == NULL) {
return 0;
}
a->top++;
a->d[i] = w;
}
return 1;
}
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
int max;
int add = 0, neg = 0;
const BIGNUM *tmp;
/* a - b a-b
* a - -b a+b
* -a - b -(a+b)
* -a - -b b-a
*/
if (a->neg) {
if (b->neg) {
tmp = a;
a = b;
b = tmp;
} else {
add = 1;
neg = 1;
}
} else {
if (b->neg) {
add = 1;
neg = 0;
}
}
if (add) {
if (!BN_uadd(r, a, b)) {
return 0;
}
r->neg = neg;
return 1;
}
/* We are actually doing a - b :-) */
max = (a->top > b->top) ? a->top : b->top;
if (bn_wexpand(r, max) == NULL) {
return 0;
}
if (BN_ucmp(a, b) < 0) {
if (!BN_usub(r, b, a)) {
return 0;
}
r->neg = 1;
} else {
if (!BN_usub(r, a, b)) {
return 0;
}
r->neg = 0;
}
return 1;
}
int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
int max, min, dif;
register BN_ULONG t1, t2, *ap, *bp, *rp;
int i, carry;
max = a->top;
min = b->top;
dif = max - min;
if (dif < 0) /* hmm... should not be happening */
{
OPENSSL_PUT_ERROR(BN, BN_R_ARG2_LT_ARG3);
return 0;
}
if (bn_wexpand(r, max) == NULL) {
return 0;
}
ap = a->d;
bp = b->d;
rp = r->d;
carry = 0;
for (i = min; i != 0; i--) {
t1 = *(ap++);
t2 = *(bp++);
if (carry) {
carry = (t1 <= t2);
t1 = (t1 - t2 - 1) & BN_MASK2;
} else {
carry = (t1 < t2);
t1 = (t1 - t2) & BN_MASK2;
}
*(rp++) = t1 & BN_MASK2;
}
if (carry) /* subtracted */
{
if (!dif) {
/* error: a < b */
return 0;
}
while (dif) {
dif--;
t1 = *(ap++);
t2 = (t1 - 1) & BN_MASK2;
*(rp++) = t2;
if (t1) {
break;
}
}
}
if (rp != ap) {
for (;;) {
if (!dif--) {
break;
}
rp[0] = ap[0];
if (!dif--) {
break;
}
rp[1] = ap[1];
if (!dif--) {
break;
}
rp[2] = ap[2];
if (!dif--) {
break;
}
rp[3] = ap[3];
rp += 4;
ap += 4;
}
}
r->top = max;
r->neg = 0;
bn_correct_top(r);
return 1;
}
int BN_sub_word(BIGNUM *a, BN_ULONG w) {
int i;
w &= BN_MASK2;
/* degenerate case: w is zero */
if (!w) {
return 1;
}
/* degenerate case: a is zero */
if (BN_is_zero(a)) {
i = BN_set_word(a, w);
if (i != 0) {
BN_set_negative(a, 1);
}
return i;
}
/* handle 'a' when negative */
if (a->neg) {
a->neg = 0;
i = BN_add_word(a, w);
a->neg = 1;
return i;
}
if ((a->top == 1) && (a->d[0] < w)) {
a->d[0] = w - a->d[0];
a->neg = 1;
return 1;
}
i = 0;
for (;;) {
if (a->d[i] >= w) {
a->d[i] -= w;
break;
} else {
a->d[i] = (a->d[i] - w) & BN_MASK2;
i++;
w = 1;
}
}
if ((a->d[i] == 0) && (i == (a->top - 1))) {
a->top--;
}
return 1;
}

View File

@ -0,0 +1,694 @@
#!/usr/bin/env perl
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
# ====================================================================
# January 2007.
# Montgomery multiplication for ARMv4.
#
# Performance improvement naturally varies among CPU implementations
# and compilers. The code was observed to provide +65-35% improvement
# [depending on key length, less for longer keys] on ARM920T, and
# +115-80% on Intel IXP425. This is compared to pre-bn_mul_mont code
# base and compiler generated code with in-lined umull and even umlal
# instructions. The latter means that this code didn't really have an
# "advantage" of utilizing some "secret" instruction.
#
# The code is interoperable with Thumb ISA and is rather compact, less
# than 1/2KB. Windows CE port would be trivial, as it's exclusively
# about decorations, ABI and instruction syntax are identical.
# November 2013
#
# Add NEON code path, which handles lengths divisible by 8. RSA/DSA
# performance improvement on Cortex-A8 is ~45-100% depending on key
# length, more for longer keys. On Cortex-A15 the span is ~10-105%.
# On Snapdragon S4 improvement was measured to vary from ~70% to
# incredible ~380%, yes, 4.8x faster, for RSA4096 sign. But this is
# rather because original integer-only code seems to perform
# suboptimally on S4. Situation on Cortex-A9 is unfortunately
# different. It's being looked into, but the trouble is that
# performance for vectors longer than 256 bits is actually couple
# of percent worse than for integer-only code. The code is chosen
# for execution on all NEON-capable processors, because gain on
# others outweighs the marginal loss on Cortex-A9.
$flavour = shift;
if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
if ($flavour && $flavour ne "void") {
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
die "can't locate arm-xlate.pl";
open STDOUT,"| \"$^X\" $xlate $flavour $output";
} else {
open STDOUT,">$output";
}
$num="r0"; # starts as num argument, but holds &tp[num-1]
$ap="r1";
$bp="r2"; $bi="r2"; $rp="r2";
$np="r3";
$tp="r4";
$aj="r5";
$nj="r6";
$tj="r7";
$n0="r8";
########### # r9 is reserved by ELF as platform specific, e.g. TLS pointer
$alo="r10"; # sl, gcc uses it to keep @GOT
$ahi="r11"; # fp
$nlo="r12"; # ip
########### # r13 is stack pointer
$nhi="r14"; # lr
########### # r15 is program counter
#### argument block layout relative to &tp[num-1], a.k.a. $num
$_rp="$num,#12*4";
# ap permanently resides in r1
$_bp="$num,#13*4";
# np permanently resides in r3
$_n0="$num,#14*4";
$_num="$num,#15*4"; $_bpend=$_num;
$code=<<___;
#include "arm_arch.h"
.text
.code 32
#if __ARM_MAX_ARCH__>=7
.align 5
.LOPENSSL_armcap:
.word OPENSSL_armcap_P-.Lbn_mul_mont
#endif
.global bn_mul_mont
.hidden bn_mul_mont
.type bn_mul_mont,%function
.align 5
bn_mul_mont:
.Lbn_mul_mont:
ldr ip,[sp,#4] @ load num
stmdb sp!,{r0,r2} @ sp points at argument block
#if __ARM_MAX_ARCH__>=7
tst ip,#7
bne .Lialu
adr r0,bn_mul_mont
ldr r2,.LOPENSSL_armcap
ldr r0,[r0,r2]
#ifdef __APPLE__
ldr r0,[r0]
#endif
tst r0,#1 @ NEON available?
ldmia sp, {r0,r2}
beq .Lialu
add sp,sp,#8
b bn_mul8x_mont_neon
.align 4
.Lialu:
#endif
cmp ip,#2
mov $num,ip @ load num
movlt r0,#0
addlt sp,sp,#2*4
blt .Labrt
stmdb sp!,{r4-r12,lr} @ save 10 registers
mov $num,$num,lsl#2 @ rescale $num for byte count
sub sp,sp,$num @ alloca(4*num)
sub sp,sp,#4 @ +extra dword
sub $num,$num,#4 @ "num=num-1"
add $tp,$bp,$num @ &bp[num-1]
add $num,sp,$num @ $num to point at &tp[num-1]
ldr $n0,[$_n0] @ &n0
ldr $bi,[$bp] @ bp[0]
ldr $aj,[$ap],#4 @ ap[0],ap++
ldr $nj,[$np],#4 @ np[0],np++
ldr $n0,[$n0] @ *n0
str $tp,[$_bpend] @ save &bp[num]
umull $alo,$ahi,$aj,$bi @ ap[0]*bp[0]
str $n0,[$_n0] @ save n0 value
mul $n0,$alo,$n0 @ "tp[0]"*n0
mov $nlo,#0
umlal $alo,$nlo,$nj,$n0 @ np[0]*n0+"t[0]"
mov $tp,sp
.L1st:
ldr $aj,[$ap],#4 @ ap[j],ap++
mov $alo,$ahi
ldr $nj,[$np],#4 @ np[j],np++
mov $ahi,#0
umlal $alo,$ahi,$aj,$bi @ ap[j]*bp[0]
mov $nhi,#0
umlal $nlo,$nhi,$nj,$n0 @ np[j]*n0
adds $nlo,$nlo,$alo
str $nlo,[$tp],#4 @ tp[j-1]=,tp++
adc $nlo,$nhi,#0
cmp $tp,$num
bne .L1st
adds $nlo,$nlo,$ahi
ldr $tp,[$_bp] @ restore bp
mov $nhi,#0
ldr $n0,[$_n0] @ restore n0
adc $nhi,$nhi,#0
str $nlo,[$num] @ tp[num-1]=
str $nhi,[$num,#4] @ tp[num]=
.Louter:
sub $tj,$num,sp @ "original" $num-1 value
sub $ap,$ap,$tj @ "rewind" ap to &ap[1]
ldr $bi,[$tp,#4]! @ *(++bp)
sub $np,$np,$tj @ "rewind" np to &np[1]
ldr $aj,[$ap,#-4] @ ap[0]
ldr $alo,[sp] @ tp[0]
ldr $nj,[$np,#-4] @ np[0]
ldr $tj,[sp,#4] @ tp[1]
mov $ahi,#0
umlal $alo,$ahi,$aj,$bi @ ap[0]*bp[i]+tp[0]
str $tp,[$_bp] @ save bp
mul $n0,$alo,$n0
mov $nlo,#0
umlal $alo,$nlo,$nj,$n0 @ np[0]*n0+"tp[0]"
mov $tp,sp
.Linner:
ldr $aj,[$ap],#4 @ ap[j],ap++
adds $alo,$ahi,$tj @ +=tp[j]
ldr $nj,[$np],#4 @ np[j],np++
mov $ahi,#0
umlal $alo,$ahi,$aj,$bi @ ap[j]*bp[i]
mov $nhi,#0
umlal $nlo,$nhi,$nj,$n0 @ np[j]*n0
adc $ahi,$ahi,#0
ldr $tj,[$tp,#8] @ tp[j+1]
adds $nlo,$nlo,$alo
str $nlo,[$tp],#4 @ tp[j-1]=,tp++
adc $nlo,$nhi,#0
cmp $tp,$num
bne .Linner
adds $nlo,$nlo,$ahi
mov $nhi,#0
ldr $tp,[$_bp] @ restore bp
adc $nhi,$nhi,#0
ldr $n0,[$_n0] @ restore n0
adds $nlo,$nlo,$tj
ldr $tj,[$_bpend] @ restore &bp[num]
adc $nhi,$nhi,#0
str $nlo,[$num] @ tp[num-1]=
str $nhi,[$num,#4] @ tp[num]=
cmp $tp,$tj
bne .Louter
ldr $rp,[$_rp] @ pull rp
add $num,$num,#4 @ $num to point at &tp[num]
sub $aj,$num,sp @ "original" num value
mov $tp,sp @ "rewind" $tp
mov $ap,$tp @ "borrow" $ap
sub $np,$np,$aj @ "rewind" $np to &np[0]
subs $tj,$tj,$tj @ "clear" carry flag
.Lsub: ldr $tj,[$tp],#4
ldr $nj,[$np],#4
sbcs $tj,$tj,$nj @ tp[j]-np[j]
str $tj,[$rp],#4 @ rp[j]=
teq $tp,$num @ preserve carry
bne .Lsub
sbcs $nhi,$nhi,#0 @ upmost carry
mov $tp,sp @ "rewind" $tp
sub $rp,$rp,$aj @ "rewind" $rp
and $ap,$tp,$nhi
bic $np,$rp,$nhi
orr $ap,$ap,$np @ ap=borrow?tp:rp
.Lcopy: ldr $tj,[$ap],#4 @ copy or in-place refresh
str sp,[$tp],#4 @ zap tp
str $tj,[$rp],#4
cmp $tp,$num
bne .Lcopy
add sp,$num,#4 @ skip over tp[num+1]
ldmia sp!,{r4-r12,lr} @ restore registers
add sp,sp,#2*4 @ skip over {r0,r2}
mov r0,#1
.Labrt:
#if __ARM_ARCH__>=5
ret @ bx lr
#else
tst lr,#1
moveq pc,lr @ be binary compatible with V4, yet
bx lr @ interoperable with Thumb ISA:-)
#endif
.size bn_mul_mont,.-bn_mul_mont
___
{
sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; }
sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; }
my ($A0,$A1,$A2,$A3)=map("d$_",(0..3));
my ($N0,$N1,$N2,$N3)=map("d$_",(4..7));
my ($Z,$Temp)=("q4","q5");
my ($A0xB,$A1xB,$A2xB,$A3xB,$A4xB,$A5xB,$A6xB,$A7xB)=map("q$_",(6..13));
my ($Bi,$Ni,$M0)=map("d$_",(28..31));
my $zero=&Dlo($Z);
my $temp=&Dlo($Temp);
my ($rptr,$aptr,$bptr,$nptr,$n0,$num)=map("r$_",(0..5));
my ($tinptr,$toutptr,$inner,$outer)=map("r$_",(6..9));
$code.=<<___;
#if __ARM_MAX_ARCH__>=7
.arch armv7-a
.fpu neon
.type bn_mul8x_mont_neon,%function
.align 5
bn_mul8x_mont_neon:
mov ip,sp
stmdb sp!,{r4-r11}
vstmdb sp!,{d8-d15} @ ABI specification says so
ldmia ip,{r4-r5} @ load rest of parameter block
sub $toutptr,sp,#16
vld1.32 {${Bi}[0]}, [$bptr,:32]!
sub $toutptr,$toutptr,$num,lsl#4
vld1.32 {$A0-$A3}, [$aptr]! @ can't specify :32 :-(
and $toutptr,$toutptr,#-64
vld1.32 {${M0}[0]}, [$n0,:32]
mov sp,$toutptr @ alloca
veor $zero,$zero,$zero
subs $inner,$num,#8
vzip.16 $Bi,$zero
vmull.u32 $A0xB,$Bi,${A0}[0]
vmull.u32 $A1xB,$Bi,${A0}[1]
vmull.u32 $A2xB,$Bi,${A1}[0]
vshl.i64 $temp,`&Dhi("$A0xB")`,#16
vmull.u32 $A3xB,$Bi,${A1}[1]
vadd.u64 $temp,$temp,`&Dlo("$A0xB")`
veor $zero,$zero,$zero
vmul.u32 $Ni,$temp,$M0
vmull.u32 $A4xB,$Bi,${A2}[0]
vld1.32 {$N0-$N3}, [$nptr]!
vmull.u32 $A5xB,$Bi,${A2}[1]
vmull.u32 $A6xB,$Bi,${A3}[0]
vzip.16 $Ni,$zero
vmull.u32 $A7xB,$Bi,${A3}[1]
bne .LNEON_1st
@ special case for num=8, everything is in register bank...
vmlal.u32 $A0xB,$Ni,${N0}[0]
sub $outer,$num,#1
vmlal.u32 $A1xB,$Ni,${N0}[1]
vmlal.u32 $A2xB,$Ni,${N1}[0]
vmlal.u32 $A3xB,$Ni,${N1}[1]
vmlal.u32 $A4xB,$Ni,${N2}[0]
vmov $Temp,$A0xB
vmlal.u32 $A5xB,$Ni,${N2}[1]
vmov $A0xB,$A1xB
vmlal.u32 $A6xB,$Ni,${N3}[0]
vmov $A1xB,$A2xB
vmlal.u32 $A7xB,$Ni,${N3}[1]
vmov $A2xB,$A3xB
vmov $A3xB,$A4xB
vshr.u64 $temp,$temp,#16
vmov $A4xB,$A5xB
vmov $A5xB,$A6xB
vadd.u64 $temp,$temp,`&Dhi("$Temp")`
vmov $A6xB,$A7xB
veor $A7xB,$A7xB
vshr.u64 $temp,$temp,#16
b .LNEON_outer8
.align 4
.LNEON_outer8:
vld1.32 {${Bi}[0]}, [$bptr,:32]!
veor $zero,$zero,$zero
vzip.16 $Bi,$zero
vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp
vmlal.u32 $A0xB,$Bi,${A0}[0]
vmlal.u32 $A1xB,$Bi,${A0}[1]
vmlal.u32 $A2xB,$Bi,${A1}[0]
vshl.i64 $temp,`&Dhi("$A0xB")`,#16
vmlal.u32 $A3xB,$Bi,${A1}[1]
vadd.u64 $temp,$temp,`&Dlo("$A0xB")`
veor $zero,$zero,$zero
subs $outer,$outer,#1
vmul.u32 $Ni,$temp,$M0
vmlal.u32 $A4xB,$Bi,${A2}[0]
vmlal.u32 $A5xB,$Bi,${A2}[1]
vmlal.u32 $A6xB,$Bi,${A3}[0]
vzip.16 $Ni,$zero
vmlal.u32 $A7xB,$Bi,${A3}[1]
vmlal.u32 $A0xB,$Ni,${N0}[0]
vmlal.u32 $A1xB,$Ni,${N0}[1]
vmlal.u32 $A2xB,$Ni,${N1}[0]
vmlal.u32 $A3xB,$Ni,${N1}[1]
vmlal.u32 $A4xB,$Ni,${N2}[0]
vmov $Temp,$A0xB
vmlal.u32 $A5xB,$Ni,${N2}[1]
vmov $A0xB,$A1xB
vmlal.u32 $A6xB,$Ni,${N3}[0]
vmov $A1xB,$A2xB
vmlal.u32 $A7xB,$Ni,${N3}[1]
vmov $A2xB,$A3xB
vmov $A3xB,$A4xB
vshr.u64 $temp,$temp,#16
vmov $A4xB,$A5xB
vmov $A5xB,$A6xB
vadd.u64 $temp,$temp,`&Dhi("$Temp")`
vmov $A6xB,$A7xB
veor $A7xB,$A7xB
vshr.u64 $temp,$temp,#16
bne .LNEON_outer8
vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp
mov $toutptr,sp
vshr.u64 $temp,`&Dlo("$A0xB")`,#16
mov $inner,$num
vadd.u64 `&Dhi("$A0xB")`,`&Dhi("$A0xB")`,$temp
add $tinptr,sp,#16
vshr.u64 $temp,`&Dhi("$A0xB")`,#16
vzip.16 `&Dlo("$A0xB")`,`&Dhi("$A0xB")`
b .LNEON_tail2
.align 4
.LNEON_1st:
vmlal.u32 $A0xB,$Ni,${N0}[0]
vld1.32 {$A0-$A3}, [$aptr]!
vmlal.u32 $A1xB,$Ni,${N0}[1]
subs $inner,$inner,#8
vmlal.u32 $A2xB,$Ni,${N1}[0]
vmlal.u32 $A3xB,$Ni,${N1}[1]
vmlal.u32 $A4xB,$Ni,${N2}[0]
vld1.32 {$N0-$N1}, [$nptr]!
vmlal.u32 $A5xB,$Ni,${N2}[1]
vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]!
vmlal.u32 $A6xB,$Ni,${N3}[0]
vmlal.u32 $A7xB,$Ni,${N3}[1]
vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]!
vmull.u32 $A0xB,$Bi,${A0}[0]
vld1.32 {$N2-$N3}, [$nptr]!
vmull.u32 $A1xB,$Bi,${A0}[1]
vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]!
vmull.u32 $A2xB,$Bi,${A1}[0]
vmull.u32 $A3xB,$Bi,${A1}[1]
vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]!
vmull.u32 $A4xB,$Bi,${A2}[0]
vmull.u32 $A5xB,$Bi,${A2}[1]
vmull.u32 $A6xB,$Bi,${A3}[0]
vmull.u32 $A7xB,$Bi,${A3}[1]
bne .LNEON_1st
vmlal.u32 $A0xB,$Ni,${N0}[0]
add $tinptr,sp,#16
vmlal.u32 $A1xB,$Ni,${N0}[1]
sub $aptr,$aptr,$num,lsl#2 @ rewind $aptr
vmlal.u32 $A2xB,$Ni,${N1}[0]
vld1.64 {$Temp}, [sp,:128]
vmlal.u32 $A3xB,$Ni,${N1}[1]
sub $outer,$num,#1
vmlal.u32 $A4xB,$Ni,${N2}[0]
vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]!
vmlal.u32 $A5xB,$Ni,${N2}[1]
vshr.u64 $temp,$temp,#16
vld1.64 {$A0xB}, [$tinptr, :128]!
vmlal.u32 $A6xB,$Ni,${N3}[0]
vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]!
vmlal.u32 $A7xB,$Ni,${N3}[1]
vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]!
vadd.u64 $temp,$temp,`&Dhi("$Temp")`
veor $Z,$Z,$Z
vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]!
vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]!
vst1.64 {$Z}, [$toutptr,:128]
vshr.u64 $temp,$temp,#16
b .LNEON_outer
.align 4
.LNEON_outer:
vld1.32 {${Bi}[0]}, [$bptr,:32]!
sub $nptr,$nptr,$num,lsl#2 @ rewind $nptr
vld1.32 {$A0-$A3}, [$aptr]!
veor $zero,$zero,$zero
mov $toutptr,sp
vzip.16 $Bi,$zero
sub $inner,$num,#8
vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp
vmlal.u32 $A0xB,$Bi,${A0}[0]
vld1.64 {$A3xB-$A4xB},[$tinptr,:256]!
vmlal.u32 $A1xB,$Bi,${A0}[1]
vmlal.u32 $A2xB,$Bi,${A1}[0]
vld1.64 {$A5xB-$A6xB},[$tinptr,:256]!
vmlal.u32 $A3xB,$Bi,${A1}[1]
vshl.i64 $temp,`&Dhi("$A0xB")`,#16
veor $zero,$zero,$zero
vadd.u64 $temp,$temp,`&Dlo("$A0xB")`
vld1.64 {$A7xB},[$tinptr,:128]!
vmul.u32 $Ni,$temp,$M0
vmlal.u32 $A4xB,$Bi,${A2}[0]
vld1.32 {$N0-$N3}, [$nptr]!
vmlal.u32 $A5xB,$Bi,${A2}[1]
vmlal.u32 $A6xB,$Bi,${A3}[0]
vzip.16 $Ni,$zero
vmlal.u32 $A7xB,$Bi,${A3}[1]
.LNEON_inner:
vmlal.u32 $A0xB,$Ni,${N0}[0]
vld1.32 {$A0-$A3}, [$aptr]!
vmlal.u32 $A1xB,$Ni,${N0}[1]
subs $inner,$inner,#8
vmlal.u32 $A2xB,$Ni,${N1}[0]
vmlal.u32 $A3xB,$Ni,${N1}[1]
vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]!
vmlal.u32 $A4xB,$Ni,${N2}[0]
vld1.64 {$A0xB}, [$tinptr, :128]!
vmlal.u32 $A5xB,$Ni,${N2}[1]
vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]!
vmlal.u32 $A6xB,$Ni,${N3}[0]
vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]!
vmlal.u32 $A7xB,$Ni,${N3}[1]
vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]!
vmlal.u32 $A0xB,$Bi,${A0}[0]
vld1.64 {$A3xB-$A4xB}, [$tinptr, :256]!
vmlal.u32 $A1xB,$Bi,${A0}[1]
vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]!
vmlal.u32 $A2xB,$Bi,${A1}[0]
vld1.64 {$A5xB-$A6xB}, [$tinptr, :256]!
vmlal.u32 $A3xB,$Bi,${A1}[1]
vld1.32 {$N0-$N3}, [$nptr]!
vmlal.u32 $A4xB,$Bi,${A2}[0]
vld1.64 {$A7xB}, [$tinptr, :128]!
vmlal.u32 $A5xB,$Bi,${A2}[1]
vmlal.u32 $A6xB,$Bi,${A3}[0]
vmlal.u32 $A7xB,$Bi,${A3}[1]
bne .LNEON_inner
vmlal.u32 $A0xB,$Ni,${N0}[0]
add $tinptr,sp,#16
vmlal.u32 $A1xB,$Ni,${N0}[1]
sub $aptr,$aptr,$num,lsl#2 @ rewind $aptr
vmlal.u32 $A2xB,$Ni,${N1}[0]
vld1.64 {$Temp}, [sp,:128]
vmlal.u32 $A3xB,$Ni,${N1}[1]
subs $outer,$outer,#1
vmlal.u32 $A4xB,$Ni,${N2}[0]
vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]!
vmlal.u32 $A5xB,$Ni,${N2}[1]
vld1.64 {$A0xB}, [$tinptr, :128]!
vshr.u64 $temp,$temp,#16
vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]!
vmlal.u32 $A6xB,$Ni,${N3}[0]
vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]!
vmlal.u32 $A7xB,$Ni,${N3}[1]
vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]!
vadd.u64 $temp,$temp,`&Dhi("$Temp")`
vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]!
vshr.u64 $temp,$temp,#16
bne .LNEON_outer
mov $toutptr,sp
mov $inner,$num
.LNEON_tail:
vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp
vld1.64 {$A3xB-$A4xB}, [$tinptr, :256]!
vshr.u64 $temp,`&Dlo("$A0xB")`,#16
vadd.u64 `&Dhi("$A0xB")`,`&Dhi("$A0xB")`,$temp
vld1.64 {$A5xB-$A6xB}, [$tinptr, :256]!
vshr.u64 $temp,`&Dhi("$A0xB")`,#16
vld1.64 {$A7xB}, [$tinptr, :128]!
vzip.16 `&Dlo("$A0xB")`,`&Dhi("$A0xB")`
.LNEON_tail2:
vadd.u64 `&Dlo("$A1xB")`,`&Dlo("$A1xB")`,$temp
vst1.32 {`&Dlo("$A0xB")`[0]}, [$toutptr, :32]!
vshr.u64 $temp,`&Dlo("$A1xB")`,#16
vadd.u64 `&Dhi("$A1xB")`,`&Dhi("$A1xB")`,$temp
vshr.u64 $temp,`&Dhi("$A1xB")`,#16
vzip.16 `&Dlo("$A1xB")`,`&Dhi("$A1xB")`
vadd.u64 `&Dlo("$A2xB")`,`&Dlo("$A2xB")`,$temp
vst1.32 {`&Dlo("$A1xB")`[0]}, [$toutptr, :32]!
vshr.u64 $temp,`&Dlo("$A2xB")`,#16
vadd.u64 `&Dhi("$A2xB")`,`&Dhi("$A2xB")`,$temp
vshr.u64 $temp,`&Dhi("$A2xB")`,#16
vzip.16 `&Dlo("$A2xB")`,`&Dhi("$A2xB")`
vadd.u64 `&Dlo("$A3xB")`,`&Dlo("$A3xB")`,$temp
vst1.32 {`&Dlo("$A2xB")`[0]}, [$toutptr, :32]!
vshr.u64 $temp,`&Dlo("$A3xB")`,#16
vadd.u64 `&Dhi("$A3xB")`,`&Dhi("$A3xB")`,$temp
vshr.u64 $temp,`&Dhi("$A3xB")`,#16
vzip.16 `&Dlo("$A3xB")`,`&Dhi("$A3xB")`
vadd.u64 `&Dlo("$A4xB")`,`&Dlo("$A4xB")`,$temp
vst1.32 {`&Dlo("$A3xB")`[0]}, [$toutptr, :32]!
vshr.u64 $temp,`&Dlo("$A4xB")`,#16
vadd.u64 `&Dhi("$A4xB")`,`&Dhi("$A4xB")`,$temp
vshr.u64 $temp,`&Dhi("$A4xB")`,#16
vzip.16 `&Dlo("$A4xB")`,`&Dhi("$A4xB")`
vadd.u64 `&Dlo("$A5xB")`,`&Dlo("$A5xB")`,$temp
vst1.32 {`&Dlo("$A4xB")`[0]}, [$toutptr, :32]!
vshr.u64 $temp,`&Dlo("$A5xB")`,#16
vadd.u64 `&Dhi("$A5xB")`,`&Dhi("$A5xB")`,$temp
vshr.u64 $temp,`&Dhi("$A5xB")`,#16
vzip.16 `&Dlo("$A5xB")`,`&Dhi("$A5xB")`
vadd.u64 `&Dlo("$A6xB")`,`&Dlo("$A6xB")`,$temp
vst1.32 {`&Dlo("$A5xB")`[0]}, [$toutptr, :32]!
vshr.u64 $temp,`&Dlo("$A6xB")`,#16
vadd.u64 `&Dhi("$A6xB")`,`&Dhi("$A6xB")`,$temp
vld1.64 {$A0xB}, [$tinptr, :128]!
vshr.u64 $temp,`&Dhi("$A6xB")`,#16
vzip.16 `&Dlo("$A6xB")`,`&Dhi("$A6xB")`
vadd.u64 `&Dlo("$A7xB")`,`&Dlo("$A7xB")`,$temp
vst1.32 {`&Dlo("$A6xB")`[0]}, [$toutptr, :32]!
vshr.u64 $temp,`&Dlo("$A7xB")`,#16
vadd.u64 `&Dhi("$A7xB")`,`&Dhi("$A7xB")`,$temp
vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]!
vshr.u64 $temp,`&Dhi("$A7xB")`,#16
vzip.16 `&Dlo("$A7xB")`,`&Dhi("$A7xB")`
subs $inner,$inner,#8
vst1.32 {`&Dlo("$A7xB")`[0]}, [$toutptr, :32]!
bne .LNEON_tail
vst1.32 {${temp}[0]}, [$toutptr, :32] @ top-most bit
sub $nptr,$nptr,$num,lsl#2 @ rewind $nptr
subs $aptr,sp,#0 @ clear carry flag
add $bptr,sp,$num,lsl#2
.LNEON_sub:
ldmia $aptr!, {r4-r7}
ldmia $nptr!, {r8-r11}
sbcs r8, r4,r8
sbcs r9, r5,r9
sbcs r10,r6,r10
sbcs r11,r7,r11
teq $aptr,$bptr @ preserves carry
stmia $rptr!, {r8-r11}
bne .LNEON_sub
ldr r10, [$aptr] @ load top-most bit
veor q0,q0,q0
sub r11,$bptr,sp @ this is num*4
veor q1,q1,q1
mov $aptr,sp
sub $rptr,$rptr,r11 @ rewind $rptr
mov $nptr,$bptr @ second 3/4th of frame
sbcs r10,r10,#0 @ result is carry flag
.LNEON_copy_n_zap:
ldmia $aptr!, {r4-r7}
ldmia $rptr, {r8-r11}
movcc r8, r4
vst1.64 {q0-q1}, [$nptr,:256]! @ wipe
movcc r9, r5
movcc r10,r6
vst1.64 {q0-q1}, [$nptr,:256]! @ wipe
movcc r11,r7
ldmia $aptr, {r4-r7}
stmia $rptr!, {r8-r11}
sub $aptr,$aptr,#16
ldmia $rptr, {r8-r11}
movcc r8, r4
vst1.64 {q0-q1}, [$aptr,:256]! @ wipe
movcc r9, r5
movcc r10,r6
vst1.64 {q0-q1}, [$nptr,:256]! @ wipe
movcc r11,r7
teq $aptr,$bptr @ preserves carry
stmia $rptr!, {r8-r11}
bne .LNEON_copy_n_zap
sub sp,ip,#96
vldmia sp!,{d8-d15}
ldmia sp!,{r4-r11}
ret @ bx lr
.size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon
#endif
___
}
$code.=<<___;
.asciz "Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
#if __ARM_MAX_ARCH__>=7
.comm OPENSSL_armcap_P,4,4
.hidden OPENSSL_armcap_P
#endif
___
$code =~ s/\`([^\`]*)\`/eval $1/gem;
$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4
$code =~ s/\bret\b/bx lr/gm;
print $code;
close STDOUT;

View File

@ -0,0 +1,774 @@
#!/usr/bin/env perl
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
&asm_init($ARGV[0],$0);
$sse2=0;
for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
&external_label("OPENSSL_ia32cap_P") if ($sse2);
&bn_mul_add_words("bn_mul_add_words");
&bn_mul_words("bn_mul_words");
&bn_sqr_words("bn_sqr_words");
&bn_div_words("bn_div_words");
&bn_add_words("bn_add_words");
&bn_sub_words("bn_sub_words");
&bn_sub_part_words("bn_sub_part_words");
&asm_finish();
sub bn_mul_add_words
{
local($name)=@_;
&function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":"");
$r="eax";
$a="edx";
$c="ecx";
if ($sse2) {
&picmeup("eax","OPENSSL_ia32cap_P");
&bt(&DWP(0,"eax"),26);
&jnc(&label("maw_non_sse2"));
&mov($r,&wparam(0));
&mov($a,&wparam(1));
&mov($c,&wparam(2));
&movd("mm0",&wparam(3)); # mm0 = w
&pxor("mm1","mm1"); # mm1 = carry_in
&jmp(&label("maw_sse2_entry"));
&set_label("maw_sse2_unrolled",16);
&movd("mm3",&DWP(0,$r,"",0)); # mm3 = r[0]
&paddq("mm1","mm3"); # mm1 = carry_in + r[0]
&movd("mm2",&DWP(0,$a,"",0)); # mm2 = a[0]
&pmuludq("mm2","mm0"); # mm2 = w*a[0]
&movd("mm4",&DWP(4,$a,"",0)); # mm4 = a[1]
&pmuludq("mm4","mm0"); # mm4 = w*a[1]
&movd("mm6",&DWP(8,$a,"",0)); # mm6 = a[2]
&pmuludq("mm6","mm0"); # mm6 = w*a[2]
&movd("mm7",&DWP(12,$a,"",0)); # mm7 = a[3]
&pmuludq("mm7","mm0"); # mm7 = w*a[3]
&paddq("mm1","mm2"); # mm1 = carry_in + r[0] + w*a[0]
&movd("mm3",&DWP(4,$r,"",0)); # mm3 = r[1]
&paddq("mm3","mm4"); # mm3 = r[1] + w*a[1]
&movd("mm5",&DWP(8,$r,"",0)); # mm5 = r[2]
&paddq("mm5","mm6"); # mm5 = r[2] + w*a[2]
&movd("mm4",&DWP(12,$r,"",0)); # mm4 = r[3]
&paddq("mm7","mm4"); # mm7 = r[3] + w*a[3]
&movd(&DWP(0,$r,"",0),"mm1");
&movd("mm2",&DWP(16,$a,"",0)); # mm2 = a[4]
&pmuludq("mm2","mm0"); # mm2 = w*a[4]
&psrlq("mm1",32); # mm1 = carry0
&movd("mm4",&DWP(20,$a,"",0)); # mm4 = a[5]
&pmuludq("mm4","mm0"); # mm4 = w*a[5]
&paddq("mm1","mm3"); # mm1 = carry0 + r[1] + w*a[1]
&movd("mm6",&DWP(24,$a,"",0)); # mm6 = a[6]
&pmuludq("mm6","mm0"); # mm6 = w*a[6]
&movd(&DWP(4,$r,"",0),"mm1");
&psrlq("mm1",32); # mm1 = carry1
&movd("mm3",&DWP(28,$a,"",0)); # mm3 = a[7]
&add($a,32);
&pmuludq("mm3","mm0"); # mm3 = w*a[7]
&paddq("mm1","mm5"); # mm1 = carry1 + r[2] + w*a[2]
&movd("mm5",&DWP(16,$r,"",0)); # mm5 = r[4]
&paddq("mm2","mm5"); # mm2 = r[4] + w*a[4]
&movd(&DWP(8,$r,"",0),"mm1");
&psrlq("mm1",32); # mm1 = carry2
&paddq("mm1","mm7"); # mm1 = carry2 + r[3] + w*a[3]
&movd("mm5",&DWP(20,$r,"",0)); # mm5 = r[5]
&paddq("mm4","mm5"); # mm4 = r[5] + w*a[5]
&movd(&DWP(12,$r,"",0),"mm1");
&psrlq("mm1",32); # mm1 = carry3
&paddq("mm1","mm2"); # mm1 = carry3 + r[4] + w*a[4]
&movd("mm5",&DWP(24,$r,"",0)); # mm5 = r[6]
&paddq("mm6","mm5"); # mm6 = r[6] + w*a[6]
&movd(&DWP(16,$r,"",0),"mm1");
&psrlq("mm1",32); # mm1 = carry4
&paddq("mm1","mm4"); # mm1 = carry4 + r[5] + w*a[5]
&movd("mm5",&DWP(28,$r,"",0)); # mm5 = r[7]
&paddq("mm3","mm5"); # mm3 = r[7] + w*a[7]
&movd(&DWP(20,$r,"",0),"mm1");
&psrlq("mm1",32); # mm1 = carry5
&paddq("mm1","mm6"); # mm1 = carry5 + r[6] + w*a[6]
&movd(&DWP(24,$r,"",0),"mm1");
&psrlq("mm1",32); # mm1 = carry6
&paddq("mm1","mm3"); # mm1 = carry6 + r[7] + w*a[7]
&movd(&DWP(28,$r,"",0),"mm1");
&lea($r,&DWP(32,$r));
&psrlq("mm1",32); # mm1 = carry_out
&sub($c,8);
&jz(&label("maw_sse2_exit"));
&set_label("maw_sse2_entry");
&test($c,0xfffffff8);
&jnz(&label("maw_sse2_unrolled"));
&set_label("maw_sse2_loop",4);
&movd("mm2",&DWP(0,$a)); # mm2 = a[i]
&movd("mm3",&DWP(0,$r)); # mm3 = r[i]
&pmuludq("mm2","mm0"); # a[i] *= w
&lea($a,&DWP(4,$a));
&paddq("mm1","mm3"); # carry += r[i]
&paddq("mm1","mm2"); # carry += a[i]*w
&movd(&DWP(0,$r),"mm1"); # r[i] = carry_low
&sub($c,1);
&psrlq("mm1",32); # carry = carry_high
&lea($r,&DWP(4,$r));
&jnz(&label("maw_sse2_loop"));
&set_label("maw_sse2_exit");
&movd("eax","mm1"); # c = carry_out
&emms();
&ret();
&set_label("maw_non_sse2",16);
}
# function_begin prologue
&push("ebp");
&push("ebx");
&push("esi");
&push("edi");
&comment("");
$Low="eax";
$High="edx";
$a="ebx";
$w="ebp";
$r="edi";
$c="esi";
&xor($c,$c); # clear carry
&mov($r,&wparam(0)); #
&mov("ecx",&wparam(2)); #
&mov($a,&wparam(1)); #
&and("ecx",0xfffffff8); # num / 8
&mov($w,&wparam(3)); #
&push("ecx"); # Up the stack for a tmp variable
&jz(&label("maw_finish"));
&set_label("maw_loop",16);
for ($i=0; $i<32; $i+=4)
{
&comment("Round $i");
&mov("eax",&DWP($i,$a)); # *a
&mul($w); # *a * w
&add("eax",$c); # L(t)+= c
&adc("edx",0); # H(t)+=carry
&add("eax",&DWP($i,$r)); # L(t)+= *r
&adc("edx",0); # H(t)+=carry
&mov(&DWP($i,$r),"eax"); # *r= L(t);
&mov($c,"edx"); # c= H(t);
}
&comment("");
&sub("ecx",8);
&lea($a,&DWP(32,$a));
&lea($r,&DWP(32,$r));
&jnz(&label("maw_loop"));
&set_label("maw_finish",0);
&mov("ecx",&wparam(2)); # get num
&and("ecx",7);
&jnz(&label("maw_finish2")); # helps branch prediction
&jmp(&label("maw_end"));
&set_label("maw_finish2",1);
for ($i=0; $i<7; $i++)
{
&comment("Tail Round $i");
&mov("eax",&DWP($i*4,$a)); # *a
&mul($w); # *a * w
&add("eax",$c); # L(t)+=c
&adc("edx",0); # H(t)+=carry
&add("eax",&DWP($i*4,$r)); # L(t)+= *r
&adc("edx",0); # H(t)+=carry
&dec("ecx") if ($i != 7-1);
&mov(&DWP($i*4,$r),"eax"); # *r= L(t);
&mov($c,"edx"); # c= H(t);
&jz(&label("maw_end")) if ($i != 7-1);
}
&set_label("maw_end",0);
&mov("eax",$c);
&pop("ecx"); # clear variable from
&function_end($name);
}
sub bn_mul_words
{
local($name)=@_;
&function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":"");
$r="eax";
$a="edx";
$c="ecx";
if ($sse2) {
&picmeup("eax","OPENSSL_ia32cap_P");
&bt(&DWP(0,"eax"),26);
&jnc(&label("mw_non_sse2"));
&mov($r,&wparam(0));
&mov($a,&wparam(1));
&mov($c,&wparam(2));
&movd("mm0",&wparam(3)); # mm0 = w
&pxor("mm1","mm1"); # mm1 = carry = 0
&set_label("mw_sse2_loop",16);
&movd("mm2",&DWP(0,$a)); # mm2 = a[i]
&pmuludq("mm2","mm0"); # a[i] *= w
&lea($a,&DWP(4,$a));
&paddq("mm1","mm2"); # carry += a[i]*w
&movd(&DWP(0,$r),"mm1"); # r[i] = carry_low
&sub($c,1);
&psrlq("mm1",32); # carry = carry_high
&lea($r,&DWP(4,$r));
&jnz(&label("mw_sse2_loop"));
&movd("eax","mm1"); # return carry
&emms();
&ret();
&set_label("mw_non_sse2",16);
}
# function_begin prologue
&push("ebp");
&push("ebx");
&push("esi");
&push("edi");
&comment("");
$Low="eax";
$High="edx";
$a="ebx";
$w="ecx";
$r="edi";
$c="esi";
$num="ebp";
&xor($c,$c); # clear carry
&mov($r,&wparam(0)); #
&mov($a,&wparam(1)); #
&mov($num,&wparam(2)); #
&mov($w,&wparam(3)); #
&and($num,0xfffffff8); # num / 8
&jz(&label("mw_finish"));
&set_label("mw_loop",0);
for ($i=0; $i<32; $i+=4)
{
&comment("Round $i");
&mov("eax",&DWP($i,$a,"",0)); # *a
&mul($w); # *a * w
&add("eax",$c); # L(t)+=c
# XXX
&adc("edx",0); # H(t)+=carry
&mov(&DWP($i,$r,"",0),"eax"); # *r= L(t);
&mov($c,"edx"); # c= H(t);
}
&comment("");
&add($a,32);
&add($r,32);
&sub($num,8);
&jz(&label("mw_finish"));
&jmp(&label("mw_loop"));
&set_label("mw_finish",0);
&mov($num,&wparam(2)); # get num
&and($num,7);
&jnz(&label("mw_finish2"));
&jmp(&label("mw_end"));
&set_label("mw_finish2",1);
for ($i=0; $i<7; $i++)
{
&comment("Tail Round $i");
&mov("eax",&DWP($i*4,$a,"",0));# *a
&mul($w); # *a * w
&add("eax",$c); # L(t)+=c
# XXX
&adc("edx",0); # H(t)+=carry
&mov(&DWP($i*4,$r,"",0),"eax");# *r= L(t);
&mov($c,"edx"); # c= H(t);
&dec($num) if ($i != 7-1);
&jz(&label("mw_end")) if ($i != 7-1);
}
&set_label("mw_end",0);
&mov("eax",$c);
&function_end($name);
}
sub bn_sqr_words
{
local($name)=@_;
&function_begin_B($name,$sse2?"EXTRN\t_OPENSSL_ia32cap_P:DWORD":"");
$r="eax";
$a="edx";
$c="ecx";
if ($sse2) {
&picmeup("eax","OPENSSL_ia32cap_P");
&bt(&DWP(0,"eax"),26);
&jnc(&label("sqr_non_sse2"));
&mov($r,&wparam(0));
&mov($a,&wparam(1));
&mov($c,&wparam(2));
&set_label("sqr_sse2_loop",16);
&movd("mm0",&DWP(0,$a)); # mm0 = a[i]
&pmuludq("mm0","mm0"); # a[i] *= a[i]
&lea($a,&DWP(4,$a)); # a++
&movq(&QWP(0,$r),"mm0"); # r[i] = a[i]*a[i]
&sub($c,1);
&lea($r,&DWP(8,$r)); # r += 2
&jnz(&label("sqr_sse2_loop"));
&emms();
&ret();
&set_label("sqr_non_sse2",16);
}
# function_begin prologue
&push("ebp");
&push("ebx");
&push("esi");
&push("edi");
&comment("");
$r="esi";
$a="edi";
$num="ebx";
&mov($r,&wparam(0)); #
&mov($a,&wparam(1)); #
&mov($num,&wparam(2)); #
&and($num,0xfffffff8); # num / 8
&jz(&label("sw_finish"));
&set_label("sw_loop",0);
for ($i=0; $i<32; $i+=4)
{
&comment("Round $i");
&mov("eax",&DWP($i,$a,"",0)); # *a
# XXX
&mul("eax"); # *a * *a
&mov(&DWP($i*2,$r,"",0),"eax"); #
&mov(&DWP($i*2+4,$r,"",0),"edx");#
}
&comment("");
&add($a,32);
&add($r,64);
&sub($num,8);
&jnz(&label("sw_loop"));
&set_label("sw_finish",0);
&mov($num,&wparam(2)); # get num
&and($num,7);
&jz(&label("sw_end"));
for ($i=0; $i<7; $i++)
{
&comment("Tail Round $i");
&mov("eax",&DWP($i*4,$a,"",0)); # *a
# XXX
&mul("eax"); # *a * *a
&mov(&DWP($i*8,$r,"",0),"eax"); #
&dec($num) if ($i != 7-1);
&mov(&DWP($i*8+4,$r,"",0),"edx");
&jz(&label("sw_end")) if ($i != 7-1);
}
&set_label("sw_end",0);
&function_end($name);
}
sub bn_div_words
{
local($name)=@_;
&function_begin_B($name,"");
&mov("edx",&wparam(0)); #
&mov("eax",&wparam(1)); #
&mov("ecx",&wparam(2)); #
&div("ecx");
&ret();
&function_end_B($name);
}
sub bn_add_words
{
local($name)=@_;
&function_begin($name,"");
&comment("");
$a="esi";
$b="edi";
$c="eax";
$r="ebx";
$tmp1="ecx";
$tmp2="edx";
$num="ebp";
&mov($r,&wparam(0)); # get r
&mov($a,&wparam(1)); # get a
&mov($b,&wparam(2)); # get b
&mov($num,&wparam(3)); # get num
&xor($c,$c); # clear carry
&and($num,0xfffffff8); # num / 8
&jz(&label("aw_finish"));
&set_label("aw_loop",0);
for ($i=0; $i<8; $i++)
{
&comment("Round $i");
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&mov($tmp2,&DWP($i*4,$b,"",0)); # *b
&add($tmp1,$c);
&mov($c,0);
&adc($c,$c);
&add($tmp1,$tmp2);
&adc($c,0);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
}
&comment("");
&add($a,32);
&add($b,32);
&add($r,32);
&sub($num,8);
&jnz(&label("aw_loop"));
&set_label("aw_finish",0);
&mov($num,&wparam(3)); # get num
&and($num,7);
&jz(&label("aw_end"));
for ($i=0; $i<7; $i++)
{
&comment("Tail Round $i");
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&mov($tmp2,&DWP($i*4,$b,"",0));# *b
&add($tmp1,$c);
&mov($c,0);
&adc($c,$c);
&add($tmp1,$tmp2);
&adc($c,0);
&dec($num) if ($i != 6);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&jz(&label("aw_end")) if ($i != 6);
}
&set_label("aw_end",0);
# &mov("eax",$c); # $c is "eax"
&function_end($name);
}
sub bn_sub_words
{
local($name)=@_;
&function_begin($name,"");
&comment("");
$a="esi";
$b="edi";
$c="eax";
$r="ebx";
$tmp1="ecx";
$tmp2="edx";
$num="ebp";
&mov($r,&wparam(0)); # get r
&mov($a,&wparam(1)); # get a
&mov($b,&wparam(2)); # get b
&mov($num,&wparam(3)); # get num
&xor($c,$c); # clear carry
&and($num,0xfffffff8); # num / 8
&jz(&label("aw_finish"));
&set_label("aw_loop",0);
for ($i=0; $i<8; $i++)
{
&comment("Round $i");
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&mov($tmp2,&DWP($i*4,$b,"",0)); # *b
&sub($tmp1,$c);
&mov($c,0);
&adc($c,$c);
&sub($tmp1,$tmp2);
&adc($c,0);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
}
&comment("");
&add($a,32);
&add($b,32);
&add($r,32);
&sub($num,8);
&jnz(&label("aw_loop"));
&set_label("aw_finish",0);
&mov($num,&wparam(3)); # get num
&and($num,7);
&jz(&label("aw_end"));
for ($i=0; $i<7; $i++)
{
&comment("Tail Round $i");
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&mov($tmp2,&DWP($i*4,$b,"",0));# *b
&sub($tmp1,$c);
&mov($c,0);
&adc($c,$c);
&sub($tmp1,$tmp2);
&adc($c,0);
&dec($num) if ($i != 6);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&jz(&label("aw_end")) if ($i != 6);
}
&set_label("aw_end",0);
# &mov("eax",$c); # $c is "eax"
&function_end($name);
}
sub bn_sub_part_words
{
local($name)=@_;
&function_begin($name,"");
&comment("");
$a="esi";
$b="edi";
$c="eax";
$r="ebx";
$tmp1="ecx";
$tmp2="edx";
$num="ebp";
&mov($r,&wparam(0)); # get r
&mov($a,&wparam(1)); # get a
&mov($b,&wparam(2)); # get b
&mov($num,&wparam(3)); # get num
&xor($c,$c); # clear carry
&and($num,0xfffffff8); # num / 8
&jz(&label("aw_finish"));
&set_label("aw_loop",0);
for ($i=0; $i<8; $i++)
{
&comment("Round $i");
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&mov($tmp2,&DWP($i*4,$b,"",0)); # *b
&sub($tmp1,$c);
&mov($c,0);
&adc($c,$c);
&sub($tmp1,$tmp2);
&adc($c,0);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
}
&comment("");
&add($a,32);
&add($b,32);
&add($r,32);
&sub($num,8);
&jnz(&label("aw_loop"));
&set_label("aw_finish",0);
&mov($num,&wparam(3)); # get num
&and($num,7);
&jz(&label("aw_end"));
for ($i=0; $i<7; $i++)
{
&comment("Tail Round $i");
&mov($tmp1,&DWP(0,$a,"",0)); # *a
&mov($tmp2,&DWP(0,$b,"",0));# *b
&sub($tmp1,$c);
&mov($c,0);
&adc($c,$c);
&sub($tmp1,$tmp2);
&adc($c,0);
&mov(&DWP(0,$r,"",0),$tmp1); # *r
&add($a, 4);
&add($b, 4);
&add($r, 4);
&dec($num) if ($i != 6);
&jz(&label("aw_end")) if ($i != 6);
}
&set_label("aw_end",0);
&cmp(&wparam(4),0);
&je(&label("pw_end"));
&mov($num,&wparam(4)); # get dl
&cmp($num,0);
&je(&label("pw_end"));
&jge(&label("pw_pos"));
&comment("pw_neg");
&mov($tmp2,0);
&sub($tmp2,$num);
&mov($num,$tmp2);
&and($num,0xfffffff8); # num / 8
&jz(&label("pw_neg_finish"));
&set_label("pw_neg_loop",0);
for ($i=0; $i<8; $i++)
{
&comment("dl<0 Round $i");
&mov($tmp1,0);
&mov($tmp2,&DWP($i*4,$b,"",0)); # *b
&sub($tmp1,$c);
&mov($c,0);
&adc($c,$c);
&sub($tmp1,$tmp2);
&adc($c,0);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
}
&comment("");
&add($b,32);
&add($r,32);
&sub($num,8);
&jnz(&label("pw_neg_loop"));
&set_label("pw_neg_finish",0);
&mov($tmp2,&wparam(4)); # get dl
&mov($num,0);
&sub($num,$tmp2);
&and($num,7);
&jz(&label("pw_end"));
for ($i=0; $i<7; $i++)
{
&comment("dl<0 Tail Round $i");
&mov($tmp1,0);
&mov($tmp2,&DWP($i*4,$b,"",0));# *b
&sub($tmp1,$c);
&mov($c,0);
&adc($c,$c);
&sub($tmp1,$tmp2);
&adc($c,0);
&dec($num) if ($i != 6);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&jz(&label("pw_end")) if ($i != 6);
}
&jmp(&label("pw_end"));
&set_label("pw_pos",0);
&and($num,0xfffffff8); # num / 8
&jz(&label("pw_pos_finish"));
&set_label("pw_pos_loop",0);
for ($i=0; $i<8; $i++)
{
&comment("dl>0 Round $i");
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&sub($tmp1,$c);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&jnc(&label("pw_nc".$i));
}
&comment("");
&add($a,32);
&add($r,32);
&sub($num,8);
&jnz(&label("pw_pos_loop"));
&set_label("pw_pos_finish",0);
&mov($num,&wparam(4)); # get dl
&and($num,7);
&jz(&label("pw_end"));
for ($i=0; $i<7; $i++)
{
&comment("dl>0 Tail Round $i");
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&sub($tmp1,$c);
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&jnc(&label("pw_tail_nc".$i));
&dec($num) if ($i != 6);
&jz(&label("pw_end")) if ($i != 6);
}
&mov($c,1);
&jmp(&label("pw_end"));
&set_label("pw_nc_loop",0);
for ($i=0; $i<8; $i++)
{
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&set_label("pw_nc".$i,0);
}
&comment("");
&add($a,32);
&add($r,32);
&sub($num,8);
&jnz(&label("pw_nc_loop"));
&mov($num,&wparam(4)); # get dl
&and($num,7);
&jz(&label("pw_nc_end"));
for ($i=0; $i<7; $i++)
{
&mov($tmp1,&DWP($i*4,$a,"",0)); # *a
&mov(&DWP($i*4,$r,"",0),$tmp1); # *r
&set_label("pw_tail_nc".$i,0);
&dec($num) if ($i != 6);
&jz(&label("pw_nc_end")) if ($i != 6);
}
&set_label("pw_nc_end",0);
&mov($c,0);
&set_label("pw_end",0);
# &mov("eax",$c); # $c is "eax"
&function_end($name);
}

View File

@ -0,0 +1,287 @@
#!/usr/local/bin/perl
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
&asm_init($ARGV[0],$0);
&bn_mul_comba("bn_mul_comba8",8);
&bn_mul_comba("bn_mul_comba4",4);
&bn_sqr_comba("bn_sqr_comba8",8);
&bn_sqr_comba("bn_sqr_comba4",4);
&asm_finish();
sub mul_add_c
{
local($a,$ai,$b,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
# pos == -1 if eax and edx are pre-loaded, 0 to load from next
# words, and 1 if load return value
&comment("mul a[$ai]*b[$bi]");
# "eax" and "edx" will always be pre-loaded.
# &mov("eax",&DWP($ai*4,$a,"",0)) ;
# &mov("edx",&DWP($bi*4,$b,"",0));
&mul("edx");
&add($c0,"eax");
&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # laod next a
&mov("eax",&wparam(0)) if $pos > 0; # load r[]
###
&adc($c1,"edx");
&mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 0; # laod next b
&mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 1; # laod next b
###
&adc($c2,0);
# is pos > 1, it means it is the last loop
&mov(&DWP($i*4,"eax","",0),$c0) if $pos > 0; # save r[];
&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # laod next a
}
sub sqr_add_c
{
local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
# pos == -1 if eax and edx are pre-loaded, 0 to load from next
# words, and 1 if load return value
&comment("sqr a[$ai]*a[$bi]");
# "eax" and "edx" will always be pre-loaded.
# &mov("eax",&DWP($ai*4,$a,"",0)) ;
# &mov("edx",&DWP($bi*4,$b,"",0));
if ($ai == $bi)
{ &mul("eax");}
else
{ &mul("edx");}
&add($c0,"eax");
&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # load next a
###
&adc($c1,"edx");
&mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos == 1) && ($na != $nb);
###
&adc($c2,0);
# is pos > 1, it means it is the last loop
&mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[];
&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b
}
sub sqr_add_c2
{
local($r,$a,$ai,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
# pos == -1 if eax and edx are pre-loaded, 0 to load from next
# words, and 1 if load return value
&comment("sqr a[$ai]*a[$bi]");
# "eax" and "edx" will always be pre-loaded.
# &mov("eax",&DWP($ai*4,$a,"",0)) ;
# &mov("edx",&DWP($bi*4,$a,"",0));
if ($ai == $bi)
{ &mul("eax");}
else
{ &mul("edx");}
&add("eax","eax");
###
&adc("edx","edx");
###
&adc($c2,0);
&add($c0,"eax");
&adc($c1,"edx");
&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 0; # load next a
&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1; # load next b
&adc($c2,0);
&mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0; # save r[];
&mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos <= 1) && ($na != $nb);
###
}
sub bn_mul_comba
{
local($name,$num)=@_;
local($a,$b,$c0,$c1,$c2);
local($i,$as,$ae,$bs,$be,$ai,$bi);
local($tot,$end);
&function_begin_B($name,"");
$c0="ebx";
$c1="ecx";
$c2="ebp";
$a="esi";
$b="edi";
$as=0;
$ae=0;
$bs=0;
$be=0;
$tot=$num+$num-1;
&push("esi");
&mov($a,&wparam(1));
&push("edi");
&mov($b,&wparam(2));
&push("ebp");
&push("ebx");
&xor($c0,$c0);
&mov("eax",&DWP(0,$a,"",0)); # load the first word
&xor($c1,$c1);
&mov("edx",&DWP(0,$b,"",0)); # load the first second
for ($i=0; $i<$tot; $i++)
{
$ai=$as;
$bi=$bs;
$end=$be+1;
&comment("################## Calculate word $i");
for ($j=$bs; $j<$end; $j++)
{
&xor($c2,$c2) if ($j == $bs);
if (($j+1) == $end)
{
$v=1;
$v=2 if (($i+1) == $tot);
}
else
{ $v=0; }
if (($j+1) != $end)
{
$na=($ai-1);
$nb=($bi+1);
}
else
{
$na=$as+($i < ($num-1));
$nb=$bs+($i >= ($num-1));
}
#printf STDERR "[$ai,$bi] -> [$na,$nb]\n";
&mul_add_c($a,$ai,$b,$bi,$c0,$c1,$c2,$v,$i,$na,$nb);
if ($v)
{
&comment("saved r[$i]");
# &mov("eax",&wparam(0));
# &mov(&DWP($i*4,"eax","",0),$c0);
($c0,$c1,$c2)=($c1,$c2,$c0);
}
$ai--;
$bi++;
}
$as++ if ($i < ($num-1));
$ae++ if ($i >= ($num-1));
$bs++ if ($i >= ($num-1));
$be++ if ($i < ($num-1));
}
&comment("save r[$i]");
# &mov("eax",&wparam(0));
&mov(&DWP($i*4,"eax","",0),$c0);
&pop("ebx");
&pop("ebp");
&pop("edi");
&pop("esi");
&ret();
&function_end_B($name);
}
sub bn_sqr_comba
{
local($name,$num)=@_;
local($r,$a,$c0,$c1,$c2)=@_;
local($i,$as,$ae,$bs,$be,$ai,$bi);
local($b,$tot,$end,$half);
&function_begin_B($name,"");
$c0="ebx";
$c1="ecx";
$c2="ebp";
$a="esi";
$r="edi";
&push("esi");
&push("edi");
&push("ebp");
&push("ebx");
&mov($r,&wparam(0));
&mov($a,&wparam(1));
&xor($c0,$c0);
&xor($c1,$c1);
&mov("eax",&DWP(0,$a,"",0)); # load the first word
$as=0;
$ae=0;
$bs=0;
$be=0;
$tot=$num+$num-1;
for ($i=0; $i<$tot; $i++)
{
$ai=$as;
$bi=$bs;
$end=$be+1;
&comment("############### Calculate word $i");
for ($j=$bs; $j<$end; $j++)
{
&xor($c2,$c2) if ($j == $bs);
if (($ai-1) < ($bi+1))
{
$v=1;
$v=2 if ($i+1) == $tot;
}
else
{ $v=0; }
if (!$v)
{
$na=$ai-1;
$nb=$bi+1;
}
else
{
$na=$as+($i < ($num-1));
$nb=$bs+($i >= ($num-1));
}
if ($ai == $bi)
{
&sqr_add_c($r,$a,$ai,$bi,
$c0,$c1,$c2,$v,$i,$na,$nb);
}
else
{
&sqr_add_c2($r,$a,$ai,$bi,
$c0,$c1,$c2,$v,$i,$na,$nb);
}
if ($v)
{
&comment("saved r[$i]");
#&mov(&DWP($i*4,$r,"",0),$c0);
($c0,$c1,$c2)=($c1,$c2,$c0);
last;
}
$ai--;
$bi++;
}
$as++ if ($i < ($num-1));
$ae++ if ($i >= ($num-1));
$bs++ if ($i >= ($num-1));
$be++ if ($i < ($num-1));
}
&mov(&DWP($i*4,$r,"",0),$c0);
&pop("ebx");
&pop("ebp");
&pop("edi");
&pop("esi");
&ret();
&function_end_B($name);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,592 @@
#!/usr/bin/env perl
# ====================================================================
# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
# ====================================================================
# October 2005
#
# This is a "teaser" code, as it can be improved in several ways...
# First of all non-SSE2 path should be implemented (yes, for now it
# performs Montgomery multiplication/convolution only on SSE2-capable
# CPUs such as P4, others fall down to original code). Then inner loop
# can be unrolled and modulo-scheduled to improve ILP and possibly
# moved to 128-bit XMM register bank (though it would require input
# rearrangement and/or increase bus bandwidth utilization). Dedicated
# squaring procedure should give further performance improvement...
# Yet, for being draft, the code improves rsa512 *sign* benchmark by
# 110%(!), rsa1024 one - by 70% and rsa4096 - by 20%:-)
# December 2006
#
# Modulo-scheduling SSE2 loops results in further 15-20% improvement.
# Integer-only code [being equipped with dedicated squaring procedure]
# gives ~40% on rsa512 sign benchmark...
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
push(@INC,"${dir}","${dir}../../perlasm");
require "x86asm.pl";
&asm_init($ARGV[0],$0);
$sse2=0;
for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); }
&external_label("OPENSSL_ia32cap_P") if ($sse2);
&function_begin("bn_mul_mont");
$i="edx";
$j="ecx";
$ap="esi"; $tp="esi"; # overlapping variables!!!
$rp="edi"; $bp="edi"; # overlapping variables!!!
$np="ebp";
$num="ebx";
$_num=&DWP(4*0,"esp"); # stack top layout
$_rp=&DWP(4*1,"esp");
$_ap=&DWP(4*2,"esp");
$_bp=&DWP(4*3,"esp");
$_np=&DWP(4*4,"esp");
$_n0=&DWP(4*5,"esp"); $_n0q=&QWP(4*5,"esp");
$_sp=&DWP(4*6,"esp");
$_bpend=&DWP(4*7,"esp");
$frame=32; # size of above frame rounded up to 16n
&xor ("eax","eax");
&mov ("edi",&wparam(5)); # int num
&cmp ("edi",4);
&jl (&label("just_leave"));
&lea ("esi",&wparam(0)); # put aside pointer to argument block
&lea ("edx",&wparam(1)); # load ap
&mov ("ebp","esp"); # saved stack pointer!
&add ("edi",2); # extra two words on top of tp
&neg ("edi");
&lea ("esp",&DWP(-$frame,"esp","edi",4)); # alloca($frame+4*(num+2))
&neg ("edi");
# minimize cache contention by arraning 2K window between stack
# pointer and ap argument [np is also position sensitive vector,
# but it's assumed to be near ap, as it's allocated at ~same
# time].
&mov ("eax","esp");
&sub ("eax","edx");
&and ("eax",2047);
&sub ("esp","eax"); # this aligns sp and ap modulo 2048
&xor ("edx","esp");
&and ("edx",2048);
&xor ("edx",2048);
&sub ("esp","edx"); # this splits them apart modulo 4096
&and ("esp",-64); # align to cache line
################################# load argument block...
&mov ("eax",&DWP(0*4,"esi"));# BN_ULONG *rp
&mov ("ebx",&DWP(1*4,"esi"));# const BN_ULONG *ap
&mov ("ecx",&DWP(2*4,"esi"));# const BN_ULONG *bp
&mov ("edx",&DWP(3*4,"esi"));# const BN_ULONG *np
&mov ("esi",&DWP(4*4,"esi"));# const BN_ULONG *n0
#&mov ("edi",&DWP(5*4,"esi"));# int num
&mov ("esi",&DWP(0,"esi")); # pull n0[0]
&mov ($_rp,"eax"); # ... save a copy of argument block
&mov ($_ap,"ebx");
&mov ($_bp,"ecx");
&mov ($_np,"edx");
&mov ($_n0,"esi");
&lea ($num,&DWP(-3,"edi")); # num=num-1 to assist modulo-scheduling
#&mov ($_num,$num); # redundant as $num is not reused
&mov ($_sp,"ebp"); # saved stack pointer!
if($sse2) {
$acc0="mm0"; # mmx register bank layout
$acc1="mm1";
$car0="mm2";
$car1="mm3";
$mul0="mm4";
$mul1="mm5";
$temp="mm6";
$mask="mm7";
&picmeup("eax","OPENSSL_ia32cap_P");
&bt (&DWP(0,"eax"),26);
&jnc (&label("non_sse2"));
&mov ("eax",-1);
&movd ($mask,"eax"); # mask 32 lower bits
&mov ($ap,$_ap); # load input pointers
&mov ($bp,$_bp);
&mov ($np,$_np);
&xor ($i,$i); # i=0
&xor ($j,$j); # j=0
&movd ($mul0,&DWP(0,$bp)); # bp[0]
&movd ($mul1,&DWP(0,$ap)); # ap[0]
&movd ($car1,&DWP(0,$np)); # np[0]
&pmuludq($mul1,$mul0); # ap[0]*bp[0]
&movq ($car0,$mul1);
&movq ($acc0,$mul1); # I wish movd worked for
&pand ($acc0,$mask); # inter-register transfers
&pmuludq($mul1,$_n0q); # *=n0
&pmuludq($car1,$mul1); # "t[0]"*np[0]*n0
&paddq ($car1,$acc0);
&movd ($acc1,&DWP(4,$np)); # np[1]
&movd ($acc0,&DWP(4,$ap)); # ap[1]
&psrlq ($car0,32);
&psrlq ($car1,32);
&inc ($j); # j++
&set_label("1st",16);
&pmuludq($acc0,$mul0); # ap[j]*bp[0]
&pmuludq($acc1,$mul1); # np[j]*m1
&paddq ($car0,$acc0); # +=c0
&paddq ($car1,$acc1); # +=c1
&movq ($acc0,$car0);
&pand ($acc0,$mask);
&movd ($acc1,&DWP(4,$np,$j,4)); # np[j+1]
&paddq ($car1,$acc0); # +=ap[j]*bp[0];
&movd ($acc0,&DWP(4,$ap,$j,4)); # ap[j+1]
&psrlq ($car0,32);
&movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[j-1]=
&psrlq ($car1,32);
&lea ($j,&DWP(1,$j));
&cmp ($j,$num);
&jl (&label("1st"));
&pmuludq($acc0,$mul0); # ap[num-1]*bp[0]
&pmuludq($acc1,$mul1); # np[num-1]*m1
&paddq ($car0,$acc0); # +=c0
&paddq ($car1,$acc1); # +=c1
&movq ($acc0,$car0);
&pand ($acc0,$mask);
&paddq ($car1,$acc0); # +=ap[num-1]*bp[0];
&movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[num-2]=
&psrlq ($car0,32);
&psrlq ($car1,32);
&paddq ($car1,$car0);
&movq (&QWP($frame,"esp",$num,4),$car1); # tp[num].tp[num-1]
&inc ($i); # i++
&set_label("outer");
&xor ($j,$j); # j=0
&movd ($mul0,&DWP(0,$bp,$i,4)); # bp[i]
&movd ($mul1,&DWP(0,$ap)); # ap[0]
&movd ($temp,&DWP($frame,"esp")); # tp[0]
&movd ($car1,&DWP(0,$np)); # np[0]
&pmuludq($mul1,$mul0); # ap[0]*bp[i]
&paddq ($mul1,$temp); # +=tp[0]
&movq ($acc0,$mul1);
&movq ($car0,$mul1);
&pand ($acc0,$mask);
&pmuludq($mul1,$_n0q); # *=n0
&pmuludq($car1,$mul1);
&paddq ($car1,$acc0);
&movd ($temp,&DWP($frame+4,"esp")); # tp[1]
&movd ($acc1,&DWP(4,$np)); # np[1]
&movd ($acc0,&DWP(4,$ap)); # ap[1]
&psrlq ($car0,32);
&psrlq ($car1,32);
&paddq ($car0,$temp); # +=tp[1]
&inc ($j); # j++
&dec ($num);
&set_label("inner");
&pmuludq($acc0,$mul0); # ap[j]*bp[i]
&pmuludq($acc1,$mul1); # np[j]*m1
&paddq ($car0,$acc0); # +=c0
&paddq ($car1,$acc1); # +=c1
&movq ($acc0,$car0);
&movd ($temp,&DWP($frame+4,"esp",$j,4));# tp[j+1]
&pand ($acc0,$mask);
&movd ($acc1,&DWP(4,$np,$j,4)); # np[j+1]
&paddq ($car1,$acc0); # +=ap[j]*bp[i]+tp[j]
&movd ($acc0,&DWP(4,$ap,$j,4)); # ap[j+1]
&psrlq ($car0,32);
&movd (&DWP($frame-4,"esp",$j,4),$car1);# tp[j-1]=
&psrlq ($car1,32);
&paddq ($car0,$temp); # +=tp[j+1]
&dec ($num);
&lea ($j,&DWP(1,$j)); # j++
&jnz (&label("inner"));
&mov ($num,$j);
&pmuludq($acc0,$mul0); # ap[num-1]*bp[i]
&pmuludq($acc1,$mul1); # np[num-1]*m1
&paddq ($car0,$acc0); # +=c0
&paddq ($car1,$acc1); # +=c1
&movq ($acc0,$car0);
&pand ($acc0,$mask);
&paddq ($car1,$acc0); # +=ap[num-1]*bp[i]+tp[num-1]
&movd (&DWP($frame-4,"esp",$j,4),$car1); # tp[num-2]=
&psrlq ($car0,32);
&psrlq ($car1,32);
&movd ($temp,&DWP($frame+4,"esp",$num,4)); # += tp[num]
&paddq ($car1,$car0);
&paddq ($car1,$temp);
&movq (&QWP($frame,"esp",$num,4),$car1); # tp[num].tp[num-1]
&lea ($i,&DWP(1,$i)); # i++
&cmp ($i,$num);
&jle (&label("outer"));
&emms (); # done with mmx bank
&jmp (&label("common_tail"));
&set_label("non_sse2",16);
}
if (0) {
&mov ("esp",$_sp);
&xor ("eax","eax"); # signal "not fast enough [yet]"
&jmp (&label("just_leave"));
# While the below code provides competitive performance for
# all key lengthes on modern Intel cores, it's still more
# than 10% slower for 4096-bit key elsewhere:-( "Competitive"
# means compared to the original integer-only assembler.
# 512-bit RSA sign is better by ~40%, but that's about all
# one can say about all CPUs...
} else {
$inp="esi"; # integer path uses these registers differently
$word="edi";
$carry="ebp";
&mov ($inp,$_ap);
&lea ($carry,&DWP(1,$num));
&mov ($word,$_bp);
&xor ($j,$j); # j=0
&mov ("edx",$inp);
&and ($carry,1); # see if num is even
&sub ("edx",$word); # see if ap==bp
&lea ("eax",&DWP(4,$word,$num,4)); # &bp[num]
&or ($carry,"edx");
&mov ($word,&DWP(0,$word)); # bp[0]
&jz (&label("bn_sqr_mont"));
&mov ($_bpend,"eax");
&mov ("eax",&DWP(0,$inp));
&xor ("edx","edx");
&set_label("mull",16);
&mov ($carry,"edx");
&mul ($word); # ap[j]*bp[0]
&add ($carry,"eax");
&lea ($j,&DWP(1,$j));
&adc ("edx",0);
&mov ("eax",&DWP(0,$inp,$j,4)); # ap[j+1]
&cmp ($j,$num);
&mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]=
&jl (&label("mull"));
&mov ($carry,"edx");
&mul ($word); # ap[num-1]*bp[0]
&mov ($word,$_n0);
&add ("eax",$carry);
&mov ($inp,$_np);
&adc ("edx",0);
&imul ($word,&DWP($frame,"esp")); # n0*tp[0]
&mov (&DWP($frame,"esp",$num,4),"eax"); # tp[num-1]=
&xor ($j,$j);
&mov (&DWP($frame+4,"esp",$num,4),"edx"); # tp[num]=
&mov (&DWP($frame+8,"esp",$num,4),$j); # tp[num+1]=
&mov ("eax",&DWP(0,$inp)); # np[0]
&mul ($word); # np[0]*m
&add ("eax",&DWP($frame,"esp")); # +=tp[0]
&mov ("eax",&DWP(4,$inp)); # np[1]
&adc ("edx",0);
&inc ($j);
&jmp (&label("2ndmadd"));
&set_label("1stmadd",16);
&mov ($carry,"edx");
&mul ($word); # ap[j]*bp[i]
&add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j]
&lea ($j,&DWP(1,$j));
&adc ("edx",0);
&add ($carry,"eax");
&mov ("eax",&DWP(0,$inp,$j,4)); # ap[j+1]
&adc ("edx",0);
&cmp ($j,$num);
&mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]=
&jl (&label("1stmadd"));
&mov ($carry,"edx");
&mul ($word); # ap[num-1]*bp[i]
&add ("eax",&DWP($frame,"esp",$num,4)); # +=tp[num-1]
&mov ($word,$_n0);
&adc ("edx",0);
&mov ($inp,$_np);
&add ($carry,"eax");
&adc ("edx",0);
&imul ($word,&DWP($frame,"esp")); # n0*tp[0]
&xor ($j,$j);
&add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num]
&mov (&DWP($frame,"esp",$num,4),$carry); # tp[num-1]=
&adc ($j,0);
&mov ("eax",&DWP(0,$inp)); # np[0]
&mov (&DWP($frame+4,"esp",$num,4),"edx"); # tp[num]=
&mov (&DWP($frame+8,"esp",$num,4),$j); # tp[num+1]=
&mul ($word); # np[0]*m
&add ("eax",&DWP($frame,"esp")); # +=tp[0]
&mov ("eax",&DWP(4,$inp)); # np[1]
&adc ("edx",0);
&mov ($j,1);
&set_label("2ndmadd",16);
&mov ($carry,"edx");
&mul ($word); # np[j]*m
&add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j]
&lea ($j,&DWP(1,$j));
&adc ("edx",0);
&add ($carry,"eax");
&mov ("eax",&DWP(0,$inp,$j,4)); # np[j+1]
&adc ("edx",0);
&cmp ($j,$num);
&mov (&DWP($frame-8,"esp",$j,4),$carry); # tp[j-1]=
&jl (&label("2ndmadd"));
&mov ($carry,"edx");
&mul ($word); # np[j]*m
&add ($carry,&DWP($frame,"esp",$num,4)); # +=tp[num-1]
&adc ("edx",0);
&add ($carry,"eax");
&adc ("edx",0);
&mov (&DWP($frame-4,"esp",$num,4),$carry); # tp[num-2]=
&xor ("eax","eax");
&mov ($j,$_bp); # &bp[i]
&add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num]
&adc ("eax",&DWP($frame+8,"esp",$num,4)); # +=tp[num+1]
&lea ($j,&DWP(4,$j));
&mov (&DWP($frame,"esp",$num,4),"edx"); # tp[num-1]=
&cmp ($j,$_bpend);
&mov (&DWP($frame+4,"esp",$num,4),"eax"); # tp[num]=
&je (&label("common_tail"));
&mov ($word,&DWP(0,$j)); # bp[i+1]
&mov ($inp,$_ap);
&mov ($_bp,$j); # &bp[++i]
&xor ($j,$j);
&xor ("edx","edx");
&mov ("eax",&DWP(0,$inp));
&jmp (&label("1stmadd"));
&set_label("bn_sqr_mont",16);
$sbit=$num;
&mov ($_num,$num);
&mov ($_bp,$j); # i=0
&mov ("eax",$word); # ap[0]
&mul ($word); # ap[0]*ap[0]
&mov (&DWP($frame,"esp"),"eax"); # tp[0]=
&mov ($sbit,"edx");
&shr ("edx",1);
&and ($sbit,1);
&inc ($j);
&set_label("sqr",16);
&mov ("eax",&DWP(0,$inp,$j,4)); # ap[j]
&mov ($carry,"edx");
&mul ($word); # ap[j]*ap[0]
&add ("eax",$carry);
&lea ($j,&DWP(1,$j));
&adc ("edx",0);
&lea ($carry,&DWP(0,$sbit,"eax",2));
&shr ("eax",31);
&cmp ($j,$_num);
&mov ($sbit,"eax");
&mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]=
&jl (&label("sqr"));
&mov ("eax",&DWP(0,$inp,$j,4)); # ap[num-1]
&mov ($carry,"edx");
&mul ($word); # ap[num-1]*ap[0]
&add ("eax",$carry);
&mov ($word,$_n0);
&adc ("edx",0);
&mov ($inp,$_np);
&lea ($carry,&DWP(0,$sbit,"eax",2));
&imul ($word,&DWP($frame,"esp")); # n0*tp[0]
&shr ("eax",31);
&mov (&DWP($frame,"esp",$j,4),$carry); # tp[num-1]=
&lea ($carry,&DWP(0,"eax","edx",2));
&mov ("eax",&DWP(0,$inp)); # np[0]
&shr ("edx",31);
&mov (&DWP($frame+4,"esp",$j,4),$carry); # tp[num]=
&mov (&DWP($frame+8,"esp",$j,4),"edx"); # tp[num+1]=
&mul ($word); # np[0]*m
&add ("eax",&DWP($frame,"esp")); # +=tp[0]
&mov ($num,$j);
&adc ("edx",0);
&mov ("eax",&DWP(4,$inp)); # np[1]
&mov ($j,1);
&set_label("3rdmadd",16);
&mov ($carry,"edx");
&mul ($word); # np[j]*m
&add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j]
&adc ("edx",0);
&add ($carry,"eax");
&mov ("eax",&DWP(4,$inp,$j,4)); # np[j+1]
&adc ("edx",0);
&mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j-1]=
&mov ($carry,"edx");
&mul ($word); # np[j+1]*m
&add ($carry,&DWP($frame+4,"esp",$j,4)); # +=tp[j+1]
&lea ($j,&DWP(2,$j));
&adc ("edx",0);
&add ($carry,"eax");
&mov ("eax",&DWP(0,$inp,$j,4)); # np[j+2]
&adc ("edx",0);
&cmp ($j,$num);
&mov (&DWP($frame-8,"esp",$j,4),$carry); # tp[j]=
&jl (&label("3rdmadd"));
&mov ($carry,"edx");
&mul ($word); # np[j]*m
&add ($carry,&DWP($frame,"esp",$num,4)); # +=tp[num-1]
&adc ("edx",0);
&add ($carry,"eax");
&adc ("edx",0);
&mov (&DWP($frame-4,"esp",$num,4),$carry); # tp[num-2]=
&mov ($j,$_bp); # i
&xor ("eax","eax");
&mov ($inp,$_ap);
&add ("edx",&DWP($frame+4,"esp",$num,4)); # carry+=tp[num]
&adc ("eax",&DWP($frame+8,"esp",$num,4)); # +=tp[num+1]
&mov (&DWP($frame,"esp",$num,4),"edx"); # tp[num-1]=
&cmp ($j,$num);
&mov (&DWP($frame+4,"esp",$num,4),"eax"); # tp[num]=
&je (&label("common_tail"));
&mov ($word,&DWP(4,$inp,$j,4)); # ap[i]
&lea ($j,&DWP(1,$j));
&mov ("eax",$word);
&mov ($_bp,$j); # ++i
&mul ($word); # ap[i]*ap[i]
&add ("eax",&DWP($frame,"esp",$j,4)); # +=tp[i]
&adc ("edx",0);
&mov (&DWP($frame,"esp",$j,4),"eax"); # tp[i]=
&xor ($carry,$carry);
&cmp ($j,$num);
&lea ($j,&DWP(1,$j));
&je (&label("sqrlast"));
&mov ($sbit,"edx"); # zaps $num
&shr ("edx",1);
&and ($sbit,1);
&set_label("sqradd",16);
&mov ("eax",&DWP(0,$inp,$j,4)); # ap[j]
&mov ($carry,"edx");
&mul ($word); # ap[j]*ap[i]
&add ("eax",$carry);
&lea ($carry,&DWP(0,"eax","eax"));
&adc ("edx",0);
&shr ("eax",31);
&add ($carry,&DWP($frame,"esp",$j,4)); # +=tp[j]
&lea ($j,&DWP(1,$j));
&adc ("eax",0);
&add ($carry,$sbit);
&adc ("eax",0);
&cmp ($j,$_num);
&mov (&DWP($frame-4,"esp",$j,4),$carry); # tp[j]=
&mov ($sbit,"eax");
&jle (&label("sqradd"));
&mov ($carry,"edx");
&add ("edx","edx");
&shr ($carry,31);
&add ("edx",$sbit);
&adc ($carry,0);
&set_label("sqrlast");
&mov ($word,$_n0);
&mov ($inp,$_np);
&imul ($word,&DWP($frame,"esp")); # n0*tp[0]
&add ("edx",&DWP($frame,"esp",$j,4)); # +=tp[num]
&mov ("eax",&DWP(0,$inp)); # np[0]
&adc ($carry,0);
&mov (&DWP($frame,"esp",$j,4),"edx"); # tp[num]=
&mov (&DWP($frame+4,"esp",$j,4),$carry); # tp[num+1]=
&mul ($word); # np[0]*m
&add ("eax",&DWP($frame,"esp")); # +=tp[0]
&lea ($num,&DWP(-1,$j));
&adc ("edx",0);
&mov ($j,1);
&mov ("eax",&DWP(4,$inp)); # np[1]
&jmp (&label("3rdmadd"));
}
&set_label("common_tail",16);
&mov ($np,$_np); # load modulus pointer
&mov ($rp,$_rp); # load result pointer
&lea ($tp,&DWP($frame,"esp")); # [$ap and $bp are zapped]
&mov ("eax",&DWP(0,$tp)); # tp[0]
&mov ($j,$num); # j=num-1
&xor ($i,$i); # i=0 and clear CF!
&set_label("sub",16);
&sbb ("eax",&DWP(0,$np,$i,4));
&mov (&DWP(0,$rp,$i,4),"eax"); # rp[i]=tp[i]-np[i]
&dec ($j); # doesn't affect CF!
&mov ("eax",&DWP(4,$tp,$i,4)); # tp[i+1]
&lea ($i,&DWP(1,$i)); # i++
&jge (&label("sub"));
&sbb ("eax",0); # handle upmost overflow bit
&set_label("copy",16); # copy or in-place refresh
&mov ("edx",&DWP(0,$tp,$num,4));
&mov ($np,&DWP(0,$rp,$num,4));
&xor ("edx",$np); # conditional select
&and ("edx","eax");
&xor ("edx",$np);
&mov (&DWP(0,$tp,$num,4),$j) # zap temporary vector
&mov (&DWP(0,$rp,$num,4),"edx"); # rp[i]=tp[i]
&dec ($num);
&jge (&label("copy"));
&mov ("esp",$_sp); # pull saved stack pointer
&mov ("eax",1);
&set_label("just_leave");
&function_end("bn_mul_mont");
&asciz("Montgomery Multiplication for x86, CRYPTOGAMS by <appro\@openssl.org>");
&asm_finish();

View File

@ -0,0 +1,599 @@
#include <openssl/bn.h>
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && !defined(OPENSSL_WINDOWS)
#include "../internal.h"
/* x86_64 BIGNUM accelerator version 0.1, December 2002.
*
* Implemented by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
* project.
*
* Rights for redistribution and usage in source and binary forms are
* granted according to the OpenSSL license. Warranty of any kind is
* disclaimed.
*
* Q. Version 0.1? It doesn't sound like Andy, he used to assign real
* versions, like 1.0...
* A. Well, that's because this code is basically a quick-n-dirty
* proof-of-concept hack. As you can see it's implemented with
* inline assembler, which means that you're bound to GCC and that
* there might be enough room for further improvement.
*
* Q. Why inline assembler?
* A. x86_64 features own ABI which I'm not familiar with. This is
* why I decided to let the compiler take care of subroutine
* prologue/epilogue as well as register allocation. For reference.
* Win64 implements different ABI for AMD64, different from Linux.
*
* Q. How much faster does it get?
* A. 'apps/openssl speed rsa dsa' output with no-asm:
*
* sign verify sign/s verify/s
* rsa 512 bits 0.0006s 0.0001s 1683.8 18456.2
* rsa 1024 bits 0.0028s 0.0002s 356.0 6407.0
* rsa 2048 bits 0.0172s 0.0005s 58.0 1957.8
* rsa 4096 bits 0.1155s 0.0018s 8.7 555.6
* sign verify sign/s verify/s
* dsa 512 bits 0.0005s 0.0006s 2100.8 1768.3
* dsa 1024 bits 0.0014s 0.0018s 692.3 559.2
* dsa 2048 bits 0.0049s 0.0061s 204.7 165.0
*
* 'apps/openssl speed rsa dsa' output with this module:
*
* sign verify sign/s verify/s
* rsa 512 bits 0.0004s 0.0000s 2767.1 33297.9
* rsa 1024 bits 0.0012s 0.0001s 867.4 14674.7
* rsa 2048 bits 0.0061s 0.0002s 164.0 5270.0
* rsa 4096 bits 0.0384s 0.0006s 26.1 1650.8
* sign verify sign/s verify/s
* dsa 512 bits 0.0002s 0.0003s 4442.2 3786.3
* dsa 1024 bits 0.0005s 0.0007s 1835.1 1497.4
* dsa 2048 bits 0.0016s 0.0020s 620.4 504.6
*
* For the reference. IA-32 assembler implementation performs
* very much like 64-bit code compiled with no-asm on the same
* machine.
*/
/* TODO(davidben): Get this file working on Windows x64. */
#undef mul
#undef mul_add
#define asm __asm__
/*
* "m"(a), "+m"(r) is the way to favor DirectPath µ-code;
* "g"(0) let the compiler to decide where does it
* want to keep the value of zero;
*/
#define mul_add(r, a, word, carry) \
do { \
register BN_ULONG high, low; \
asm("mulq %3" : "=a"(low), "=d"(high) : "a"(word), "m"(a) : "cc"); \
asm("addq %2,%0; adcq %3,%1" \
: "+r"(carry), "+d"(high) \
: "a"(low), "g"(0) \
: "cc"); \
asm("addq %2,%0; adcq %3,%1" \
: "+m"(r), "+d"(high) \
: "r"(carry), "g"(0) \
: "cc"); \
carry = high; \
} while (0)
#define mul(r, a, word, carry) \
do { \
register BN_ULONG high, low; \
asm("mulq %3" : "=a"(low), "=d"(high) : "a"(word), "g"(a) : "cc"); \
asm("addq %2,%0; adcq %3,%1" \
: "+r"(carry), "+d"(high) \
: "a"(low), "g"(0) \
: "cc"); \
(r) = carry, carry = high; \
} while (0)
#undef sqr
#define sqr(r0, r1, a) asm("mulq %2" : "=a"(r0), "=d"(r1) : "a"(a) : "cc");
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
BN_ULONG w) {
BN_ULONG c1 = 0;
if (num <= 0) {
return (c1);
}
while (num & ~3) {
mul_add(rp[0], ap[0], w, c1);
mul_add(rp[1], ap[1], w, c1);
mul_add(rp[2], ap[2], w, c1);
mul_add(rp[3], ap[3], w, c1);
ap += 4;
rp += 4;
num -= 4;
}
if (num) {
mul_add(rp[0], ap[0], w, c1);
if (--num == 0) {
return c1;
}
mul_add(rp[1], ap[1], w, c1);
if (--num == 0) {
return c1;
}
mul_add(rp[2], ap[2], w, c1);
return c1;
}
return c1;
}
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
BN_ULONG c1 = 0;
if (num <= 0) {
return c1;
}
while (num & ~3) {
mul(rp[0], ap[0], w, c1);
mul(rp[1], ap[1], w, c1);
mul(rp[2], ap[2], w, c1);
mul(rp[3], ap[3], w, c1);
ap += 4;
rp += 4;
num -= 4;
}
if (num) {
mul(rp[0], ap[0], w, c1);
if (--num == 0) {
return c1;
}
mul(rp[1], ap[1], w, c1);
if (--num == 0) {
return c1;
}
mul(rp[2], ap[2], w, c1);
}
return c1;
}
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
if (n <= 0) {
return;
}
while (n & ~3) {
sqr(r[0], r[1], a[0]);
sqr(r[2], r[3], a[1]);
sqr(r[4], r[5], a[2]);
sqr(r[6], r[7], a[3]);
a += 4;
r += 8;
n -= 4;
}
if (n) {
sqr(r[0], r[1], a[0]);
if (--n == 0) {
return;
}
sqr(r[2], r[3], a[1]);
if (--n == 0) {
return;
}
sqr(r[4], r[5], a[2]);
}
}
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
BN_ULONG ret, waste;
asm("divq %4" : "=a"(ret), "=d"(waste) : "a"(l), "d"(h), "g"(d) : "cc");
return ret;
}
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
int n) {
BN_ULONG ret;
size_t i = 0;
if (n <= 0) {
return 0;
}
asm volatile (
" subq %0,%0 \n" /* clear carry */
" jmp 1f \n"
".p2align 4 \n"
"1: movq (%4,%2,8),%0 \n"
" adcq (%5,%2,8),%0 \n"
" movq %0,(%3,%2,8) \n"
" lea 1(%2),%2 \n"
" loop 1b \n"
" sbbq %0,%0 \n"
: "=&r"(ret), "+c"(n), "+r"(i)
: "r"(rp), "r"(ap), "r"(bp)
: "cc", "memory");
return ret & 1;
}
#ifndef SIMICS
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
int n) {
BN_ULONG ret;
size_t i = 0;
if (n <= 0) {
return 0;
}
asm volatile (
" subq %0,%0 \n" /* clear borrow */
" jmp 1f \n"
".p2align 4 \n"
"1: movq (%4,%2,8),%0 \n"
" sbbq (%5,%2,8),%0 \n"
" movq %0,(%3,%2,8) \n"
" lea 1(%2),%2 \n"
" loop 1b \n"
" sbbq %0,%0 \n"
: "=&r"(ret), "+c"(n), "+r"(i)
: "r"(rp), "r"(ap), "r"(bp)
: "cc", "memory");
return ret & 1;
}
#else
/* Simics 1.4<7 has buggy sbbq:-( */
#define BN_MASK2 0xffffffffffffffffL
BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
BN_ULONG t1, t2;
int c = 0;
if (n <= 0) {
return (BN_ULONG)0;
}
for (;;) {
t1 = a[0];
t2 = b[0];
r[0] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2) {
c = (t1 < t2);
}
if (--n <= 0) {
break;
}
t1 = a[1];
t2 = b[1];
r[1] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2) {
c = (t1 < t2);
}
if (--n <= 0) {
break;
}
t1 = a[2];
t2 = b[2];
r[2] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2) {
c = (t1 < t2);
}
if (--n <= 0) {
break;
}
t1 = a[3];
t2 = b[3];
r[3] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2) {
c = (t1 < t2);
}
if (--n <= 0) {
break;
}
a += 4;
b += 4;
r += 4;
}
return c;
}
#endif
/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */
/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0)
*/
/* Keep in mind that carrying into high part of multiplication result can not
* overflow, because it cannot be all-ones. */
#define mul_add_c(a, b, c0, c1, c2) \
do { \
BN_ULONG t1, t2; \
asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
: "+r"(c0), "+r"(c1), "+r"(c2) \
: "r"(t1), "r"(t2), "g"(0) \
: "cc"); \
} while (0)
#define sqr_add_c(a, i, c0, c1, c2) \
do { \
BN_ULONG t1, t2; \
asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"(a[i]) : "cc"); \
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
: "+r"(c0), "+r"(c1), "+r"(c2) \
: "r"(t1), "r"(t2), "g"(0) \
: "cc"); \
} while (0)
#define mul_add_c2(a, b, c0, c1, c2) \
do { \
BN_ULONG t1, t2; \
asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
: "+r"(c0), "+r"(c1), "+r"(c2) \
: "r"(t1), "r"(t2), "g"(0) \
: "cc"); \
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
: "+r"(c0), "+r"(c1), "+r"(c2) \
: "r"(t1), "r"(t2), "g"(0) \
: "cc"); \
} while (0)
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
BN_ULONG c1, c2, c3;
c1 = 0;
c2 = 0;
c3 = 0;
mul_add_c(a[0], b[0], c1, c2, c3);
r[0] = c1;
c1 = 0;
mul_add_c(a[0], b[1], c2, c3, c1);
mul_add_c(a[1], b[0], c2, c3, c1);
r[1] = c2;
c2 = 0;
mul_add_c(a[2], b[0], c3, c1, c2);
mul_add_c(a[1], b[1], c3, c1, c2);
mul_add_c(a[0], b[2], c3, c1, c2);
r[2] = c3;
c3 = 0;
mul_add_c(a[0], b[3], c1, c2, c3);
mul_add_c(a[1], b[2], c1, c2, c3);
mul_add_c(a[2], b[1], c1, c2, c3);
mul_add_c(a[3], b[0], c1, c2, c3);
r[3] = c1;
c1 = 0;
mul_add_c(a[4], b[0], c2, c3, c1);
mul_add_c(a[3], b[1], c2, c3, c1);
mul_add_c(a[2], b[2], c2, c3, c1);
mul_add_c(a[1], b[3], c2, c3, c1);
mul_add_c(a[0], b[4], c2, c3, c1);
r[4] = c2;
c2 = 0;
mul_add_c(a[0], b[5], c3, c1, c2);
mul_add_c(a[1], b[4], c3, c1, c2);
mul_add_c(a[2], b[3], c3, c1, c2);
mul_add_c(a[3], b[2], c3, c1, c2);
mul_add_c(a[4], b[1], c3, c1, c2);
mul_add_c(a[5], b[0], c3, c1, c2);
r[5] = c3;
c3 = 0;
mul_add_c(a[6], b[0], c1, c2, c3);
mul_add_c(a[5], b[1], c1, c2, c3);
mul_add_c(a[4], b[2], c1, c2, c3);
mul_add_c(a[3], b[3], c1, c2, c3);
mul_add_c(a[2], b[4], c1, c2, c3);
mul_add_c(a[1], b[5], c1, c2, c3);
mul_add_c(a[0], b[6], c1, c2, c3);
r[6] = c1;
c1 = 0;
mul_add_c(a[0], b[7], c2, c3, c1);
mul_add_c(a[1], b[6], c2, c3, c1);
mul_add_c(a[2], b[5], c2, c3, c1);
mul_add_c(a[3], b[4], c2, c3, c1);
mul_add_c(a[4], b[3], c2, c3, c1);
mul_add_c(a[5], b[2], c2, c3, c1);
mul_add_c(a[6], b[1], c2, c3, c1);
mul_add_c(a[7], b[0], c2, c3, c1);
r[7] = c2;
c2 = 0;
mul_add_c(a[7], b[1], c3, c1, c2);
mul_add_c(a[6], b[2], c3, c1, c2);
mul_add_c(a[5], b[3], c3, c1, c2);
mul_add_c(a[4], b[4], c3, c1, c2);
mul_add_c(a[3], b[5], c3, c1, c2);
mul_add_c(a[2], b[6], c3, c1, c2);
mul_add_c(a[1], b[7], c3, c1, c2);
r[8] = c3;
c3 = 0;
mul_add_c(a[2], b[7], c1, c2, c3);
mul_add_c(a[3], b[6], c1, c2, c3);
mul_add_c(a[4], b[5], c1, c2, c3);
mul_add_c(a[5], b[4], c1, c2, c3);
mul_add_c(a[6], b[3], c1, c2, c3);
mul_add_c(a[7], b[2], c1, c2, c3);
r[9] = c1;
c1 = 0;
mul_add_c(a[7], b[3], c2, c3, c1);
mul_add_c(a[6], b[4], c2, c3, c1);
mul_add_c(a[5], b[5], c2, c3, c1);
mul_add_c(a[4], b[6], c2, c3, c1);
mul_add_c(a[3], b[7], c2, c3, c1);
r[10] = c2;
c2 = 0;
mul_add_c(a[4], b[7], c3, c1, c2);
mul_add_c(a[5], b[6], c3, c1, c2);
mul_add_c(a[6], b[5], c3, c1, c2);
mul_add_c(a[7], b[4], c3, c1, c2);
r[11] = c3;
c3 = 0;
mul_add_c(a[7], b[5], c1, c2, c3);
mul_add_c(a[6], b[6], c1, c2, c3);
mul_add_c(a[5], b[7], c1, c2, c3);
r[12] = c1;
c1 = 0;
mul_add_c(a[6], b[7], c2, c3, c1);
mul_add_c(a[7], b[6], c2, c3, c1);
r[13] = c2;
c2 = 0;
mul_add_c(a[7], b[7], c3, c1, c2);
r[14] = c3;
r[15] = c1;
}
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
BN_ULONG c1, c2, c3;
c1 = 0;
c2 = 0;
c3 = 0;
mul_add_c(a[0], b[0], c1, c2, c3);
r[0] = c1;
c1 = 0;
mul_add_c(a[0], b[1], c2, c3, c1);
mul_add_c(a[1], b[0], c2, c3, c1);
r[1] = c2;
c2 = 0;
mul_add_c(a[2], b[0], c3, c1, c2);
mul_add_c(a[1], b[1], c3, c1, c2);
mul_add_c(a[0], b[2], c3, c1, c2);
r[2] = c3;
c3 = 0;
mul_add_c(a[0], b[3], c1, c2, c3);
mul_add_c(a[1], b[2], c1, c2, c3);
mul_add_c(a[2], b[1], c1, c2, c3);
mul_add_c(a[3], b[0], c1, c2, c3);
r[3] = c1;
c1 = 0;
mul_add_c(a[3], b[1], c2, c3, c1);
mul_add_c(a[2], b[2], c2, c3, c1);
mul_add_c(a[1], b[3], c2, c3, c1);
r[4] = c2;
c2 = 0;
mul_add_c(a[2], b[3], c3, c1, c2);
mul_add_c(a[3], b[2], c3, c1, c2);
r[5] = c3;
c3 = 0;
mul_add_c(a[3], b[3], c1, c2, c3);
r[6] = c1;
r[7] = c2;
}
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
BN_ULONG c1, c2, c3;
c1 = 0;
c2 = 0;
c3 = 0;
sqr_add_c(a, 0, c1, c2, c3);
r[0] = c1;
c1 = 0;
sqr_add_c2(a, 1, 0, c2, c3, c1);
r[1] = c2;
c2 = 0;
sqr_add_c(a, 1, c3, c1, c2);
sqr_add_c2(a, 2, 0, c3, c1, c2);
r[2] = c3;
c3 = 0;
sqr_add_c2(a, 3, 0, c1, c2, c3);
sqr_add_c2(a, 2, 1, c1, c2, c3);
r[3] = c1;
c1 = 0;
sqr_add_c(a, 2, c2, c3, c1);
sqr_add_c2(a, 3, 1, c2, c3, c1);
sqr_add_c2(a, 4, 0, c2, c3, c1);
r[4] = c2;
c2 = 0;
sqr_add_c2(a, 5, 0, c3, c1, c2);
sqr_add_c2(a, 4, 1, c3, c1, c2);
sqr_add_c2(a, 3, 2, c3, c1, c2);
r[5] = c3;
c3 = 0;
sqr_add_c(a, 3, c1, c2, c3);
sqr_add_c2(a, 4, 2, c1, c2, c3);
sqr_add_c2(a, 5, 1, c1, c2, c3);
sqr_add_c2(a, 6, 0, c1, c2, c3);
r[6] = c1;
c1 = 0;
sqr_add_c2(a, 7, 0, c2, c3, c1);
sqr_add_c2(a, 6, 1, c2, c3, c1);
sqr_add_c2(a, 5, 2, c2, c3, c1);
sqr_add_c2(a, 4, 3, c2, c3, c1);
r[7] = c2;
c2 = 0;
sqr_add_c(a, 4, c3, c1, c2);
sqr_add_c2(a, 5, 3, c3, c1, c2);
sqr_add_c2(a, 6, 2, c3, c1, c2);
sqr_add_c2(a, 7, 1, c3, c1, c2);
r[8] = c3;
c3 = 0;
sqr_add_c2(a, 7, 2, c1, c2, c3);
sqr_add_c2(a, 6, 3, c1, c2, c3);
sqr_add_c2(a, 5, 4, c1, c2, c3);
r[9] = c1;
c1 = 0;
sqr_add_c(a, 5, c2, c3, c1);
sqr_add_c2(a, 6, 4, c2, c3, c1);
sqr_add_c2(a, 7, 3, c2, c3, c1);
r[10] = c2;
c2 = 0;
sqr_add_c2(a, 7, 4, c3, c1, c2);
sqr_add_c2(a, 6, 5, c3, c1, c2);
r[11] = c3;
c3 = 0;
sqr_add_c(a, 6, c1, c2, c3);
sqr_add_c2(a, 7, 5, c1, c2, c3);
r[12] = c1;
c1 = 0;
sqr_add_c2(a, 7, 6, c2, c3, c1);
r[13] = c2;
c2 = 0;
sqr_add_c(a, 7, c3, c1, c2);
r[14] = c3;
r[15] = c1;
}
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
BN_ULONG c1, c2, c3;
c1 = 0;
c2 = 0;
c3 = 0;
sqr_add_c(a, 0, c1, c2, c3);
r[0] = c1;
c1 = 0;
sqr_add_c2(a, 1, 0, c2, c3, c1);
r[1] = c2;
c2 = 0;
sqr_add_c(a, 1, c3, c1, c2);
sqr_add_c2(a, 2, 0, c3, c1, c2);
r[2] = c3;
c3 = 0;
sqr_add_c2(a, 3, 0, c1, c2, c3);
sqr_add_c2(a, 2, 1, c1, c2, c3);
r[3] = c1;
c1 = 0;
sqr_add_c(a, 2, c2, c3, c1);
sqr_add_c2(a, 3, 1, c2, c3, c1);
r[4] = c2;
c2 = 0;
sqr_add_c2(a, 3, 2, c3, c1, c2);
r[5] = c3;
c3 = 0;
sqr_add_c(a, 3, c1, c2, c3);
r[6] = c1;
r[7] = c2;
}
#endif /* !NO_ASM && X86_64 && !WINDOWS */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More